blob: beb7c0944d7571752ceb504c62bb386ab223734b [file] [log] [blame]
Eric Laurent4e090692015-03-05 15:12:40 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "RadioService"
18//#define LOG_NDEBUG 0
19
20#include <stdio.h>
21#include <string.h>
22#include <sys/types.h>
23#include <pthread.h>
24
Eric Laurent53810822015-03-12 09:12:01 -070025#include <system/audio.h>
26#include <system/audio_policy.h>
Eric Laurent4e090692015-03-05 15:12:40 -080027#include <system/radio.h>
28#include <system/radio_metadata.h>
29#include <cutils/atomic.h>
30#include <cutils/properties.h>
31#include <hardware/hardware.h>
32#include <utils/Errors.h>
33#include <utils/Log.h>
34#include <binder/IServiceManager.h>
35#include <binder/MemoryBase.h>
36#include <binder/MemoryHeapBase.h>
Keun-young Park0e378542017-06-01 18:22:05 -070037#include <binder/PermissionCache.h>
Eric Laurent4e090692015-03-05 15:12:40 -080038#include <hardware/radio.h>
Eric Laurent53810822015-03-12 09:12:01 -070039#include <media/AudioSystem.h>
Eric Laurent4e090692015-03-05 15:12:40 -080040#include "RadioService.h"
41#include "RadioRegions.h"
42
43namespace android {
44
Eric Laurent53810822015-03-12 09:12:01 -070045static const char kRadioTunerAudioDeviceName[] = "Radio tuner source";
Eric Laurent4e090692015-03-05 15:12:40 -080046
Keun-young Park0e378542017-06-01 18:22:05 -070047static const String16 RADIO_PERMISSION("android.permission.ACCESS_FM_RADIO");
48
Eric Laurent4e090692015-03-05 15:12:40 -080049RadioService::RadioService()
50 : BnRadioService(), mNextUniqueId(1)
51{
52 ALOGI("%s", __FUNCTION__);
53}
54
55void RadioService::onFirstRef()
56{
Eric Laurent4e090692015-03-05 15:12:40 -080057 ALOGI("%s", __FUNCTION__);
58
Eric Laurent01d267e2016-10-21 08:16:10 -070059 sp<RadioInterface> dev = RadioInterface::connectModule(RADIO_CLASS_AM_FM);
Eric Laurent4e090692015-03-05 15:12:40 -080060
Eric Laurent01d267e2016-10-21 08:16:10 -070061 if (dev == 0) {
62 return;
63 }
Eric Laurent4e090692015-03-05 15:12:40 -080064 struct radio_hal_properties halProperties;
Eric Laurent01d267e2016-10-21 08:16:10 -070065 int rc = dev->getProperties(&halProperties);
Eric Laurent4e090692015-03-05 15:12:40 -080066 if (rc != 0) {
67 ALOGE("could not read implementation properties");
68 return;
69 }
70
71 radio_properties_t properties;
72 properties.handle =
73 (radio_handle_t)android_atomic_inc(&mNextUniqueId);
Eric Laurent4e090692015-03-05 15:12:40 -080074 convertProperties(&properties, &halProperties);
Tomasz Wasilczyk164f3682017-02-08 09:18:08 -080075
76 ALOGI("loaded default module %s, ver %s, handle %d", properties.product,
77 properties.version, properties.handle);
78
Eric Laurent53810822015-03-12 09:12:01 -070079 sp<Module> module = new Module(dev, properties);
Eric Laurent4e090692015-03-05 15:12:40 -080080 mModules.add(properties.handle, module);
81}
82
83RadioService::~RadioService()
84{
Eric Laurent4e090692015-03-05 15:12:40 -080085}
86
87status_t RadioService::listModules(struct radio_properties *properties,
88 uint32_t *numModules)
89{
Keun-young Park0e378542017-06-01 18:22:05 -070090 if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
91 return PERMISSION_DENIED;
92 }
Eric Laurent4e090692015-03-05 15:12:40 -080093 ALOGV("listModules");
94
95 AutoMutex lock(mServiceLock);
96 if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
97 return BAD_VALUE;
98 }
Eric Laurent01d267e2016-10-21 08:16:10 -070099 uint32_t maxModules = *numModules;
Eric Laurent4e090692015-03-05 15:12:40 -0800100 *numModules = mModules.size();
101 for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
102 properties[i] = mModules.valueAt(i)->properties();
103 }
104 return NO_ERROR;
105}
106
107status_t RadioService::attach(radio_handle_t handle,
108 const sp<IRadioClient>& client,
109 const struct radio_band_config *config,
110 bool withAudio,
111 sp<IRadio>& radio)
112{
Keun-young Park0e378542017-06-01 18:22:05 -0700113 if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
114 return PERMISSION_DENIED;
115 }
Eric Laurent4e090692015-03-05 15:12:40 -0800116 ALOGV("%s %d config %p withAudio %d", __FUNCTION__, handle, config, withAudio);
117
118 AutoMutex lock(mServiceLock);
119 radio.clear();
120 if (client == 0) {
121 return BAD_VALUE;
122 }
123 ssize_t index = mModules.indexOfKey(handle);
124 if (index < 0) {
125 return BAD_VALUE;
126 }
127 sp<Module> module = mModules.valueAt(index);
128
129 if (config == NULL) {
130 config = module->getDefaultConfig();
131 if (config == NULL) {
132 return INVALID_OPERATION;
133 }
134 }
135 ALOGV("%s region %d type %d", __FUNCTION__, config->region, config->band.type);
136
137 radio = module->addClient(client, config, withAudio);
138
139 if (radio == 0) {
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700140 return NO_INIT;
Eric Laurent4e090692015-03-05 15:12:40 -0800141 }
142 return NO_ERROR;
143}
144
145
146static const int kDumpLockRetries = 50;
147static const int kDumpLockSleep = 60000;
148
149static bool tryLock(Mutex& mutex)
150{
151 bool locked = false;
152 for (int i = 0; i < kDumpLockRetries; ++i) {
153 if (mutex.tryLock() == NO_ERROR) {
154 locked = true;
155 break;
156 }
157 usleep(kDumpLockSleep);
158 }
159 return locked;
160}
161
162status_t RadioService::dump(int fd, const Vector<String16>& args __unused) {
163 String8 result;
164 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
165 result.appendFormat("Permission Denial: can't dump RadioService");
166 write(fd, result.string(), result.size());
167 } else {
168 bool locked = tryLock(mServiceLock);
169 // failed to lock - RadioService is probably deadlocked
170 if (!locked) {
171 result.append("RadioService may be deadlocked\n");
172 write(fd, result.string(), result.size());
173 }
174
175 if (locked) mServiceLock.unlock();
176 }
177 return NO_ERROR;
178}
179
180status_t RadioService::onTransact(
181 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
182 return BnRadioService::onTransact(code, data, reply, flags);
183}
184
185
Eric Laurent4e090692015-03-05 15:12:40 -0800186/* static */
187void RadioService::convertProperties(radio_properties_t *properties,
188 const radio_hal_properties_t *halProperties)
189{
190 memset(properties, 0, sizeof(struct radio_properties));
191 properties->class_id = halProperties->class_id;
192 strlcpy(properties->implementor, halProperties->implementor,
193 RADIO_STRING_LEN_MAX);
194 strlcpy(properties->product, halProperties->product,
195 RADIO_STRING_LEN_MAX);
196 strlcpy(properties->version, halProperties->version,
197 RADIO_STRING_LEN_MAX);
198 strlcpy(properties->serial, halProperties->serial,
199 RADIO_STRING_LEN_MAX);
200 properties->num_tuners = halProperties->num_tuners;
201 properties->num_audio_sources = halProperties->num_audio_sources;
202 properties->supports_capture = halProperties->supports_capture;
203
204 for (size_t i = 0; i < ARRAY_SIZE(sKnownRegionConfigs); i++) {
205 const radio_hal_band_config_t *band = &sKnownRegionConfigs[i].band;
206 size_t j;
207 for (j = 0; j < halProperties->num_bands; j++) {
208 const radio_hal_band_config_t *halBand = &halProperties->bands[j];
209 size_t k;
210 if (band->type != halBand->type) continue;
211 if (band->lower_limit < halBand->lower_limit) continue;
212 if (band->upper_limit > halBand->upper_limit) continue;
213 for (k = 0; k < halBand->num_spacings; k++) {
214 if (band->spacings[0] == halBand->spacings[k]) break;
215 }
216 if (k == halBand->num_spacings) continue;
217 if (band->type == RADIO_BAND_AM) break;
218 if ((band->fm.deemphasis & halBand->fm.deemphasis) == 0) continue;
219 if (halBand->fm.rds == 0) break;
220 if ((band->fm.rds & halBand->fm.rds) != 0) break;
221 }
222 if (j == halProperties->num_bands) continue;
223
224 ALOGI("convertProperties() Adding band type %d region %d",
225 sKnownRegionConfigs[i].band.type , sKnownRegionConfigs[i].region);
226
227 memcpy(&properties->bands[properties->num_bands++],
228 &sKnownRegionConfigs[i],
229 sizeof(radio_band_config_t));
230 }
231}
232
233#undef LOG_TAG
234#define LOG_TAG "RadioService::CallbackThread"
235
236RadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient)
237 : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService"))
238{
239}
240
241RadioService::CallbackThread::~CallbackThread()
242{
243 mEventQueue.clear();
244}
245
246void RadioService::CallbackThread::onFirstRef()
247{
248 run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO);
249}
250
251bool RadioService::CallbackThread::threadLoop()
252{
253 while (!exitPending()) {
254 sp<IMemory> eventMemory;
255 sp<ModuleClient> moduleClient;
256 {
257 Mutex::Autolock _l(mCallbackLock);
258 while (mEventQueue.isEmpty() && !exitPending()) {
259 ALOGV("CallbackThread::threadLoop() sleep");
260 mCallbackCond.wait(mCallbackLock);
261 ALOGV("CallbackThread::threadLoop() wake up");
262 }
263 if (exitPending()) {
264 break;
265 }
266 eventMemory = mEventQueue[0];
267 mEventQueue.removeAt(0);
268 moduleClient = mModuleClient.promote();
269 }
270 if (moduleClient != 0) {
271 moduleClient->onCallbackEvent(eventMemory);
272 eventMemory.clear();
273 }
274 }
275 return false;
276}
277
278void RadioService::CallbackThread::exit()
279{
280 Mutex::Autolock _l(mCallbackLock);
281 requestExit();
282 mCallbackCond.broadcast();
283}
284
285sp<IMemory> RadioService::CallbackThread::prepareEvent(radio_hal_event_t *halEvent)
286{
287 sp<IMemory> eventMemory;
288
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700289 // The event layout in shared memory is:
290 // sizeof(struct radio_event) bytes : the event itself
291 // 4 bytes : metadata size or 0
292 // N bytes : metadata if present
293 uint32_t metadataOffset = sizeof(struct radio_event) + sizeof(uint32_t);
294 uint32_t metadataSize = 0;
295
Eric Laurent4e090692015-03-05 15:12:40 -0800296 switch (halEvent->type) {
297 case RADIO_EVENT_TUNED:
298 case RADIO_EVENT_AF_SWITCH:
299 if (radio_metadata_check(halEvent->info.metadata) == 0) {
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700300 metadataSize = (uint32_t)radio_metadata_get_size(halEvent->info.metadata);
Eric Laurent4e090692015-03-05 15:12:40 -0800301 }
302 break;
303 case RADIO_EVENT_METADATA:
304 if (radio_metadata_check(halEvent->metadata) != 0) {
305 return eventMemory;
306 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700307 metadataSize = (uint32_t)radio_metadata_get_size(halEvent->metadata);
Eric Laurent4e090692015-03-05 15:12:40 -0800308 break;
309 default:
310 break;
311 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700312
313 eventMemory = mMemoryDealer->allocate(metadataOffset + metadataSize);
Eric Laurent4e090692015-03-05 15:12:40 -0800314 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
315 eventMemory.clear();
316 return eventMemory;
317 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700318
Eric Laurent4e090692015-03-05 15:12:40 -0800319 struct radio_event *event = (struct radio_event *)eventMemory->pointer();
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700320
321 *(uint32_t *)((uint8_t *)event + metadataOffset - sizeof(uint32_t)) = metadataSize;
322
Eric Laurent4e090692015-03-05 15:12:40 -0800323 event->type = halEvent->type;
324 event->status = halEvent->status;
325
326 switch (event->type) {
327 case RADIO_EVENT_CONFIG:
328 event->config.band = halEvent->config;
329 break;
330 case RADIO_EVENT_TUNED:
331 case RADIO_EVENT_AF_SWITCH:
332 event->info = halEvent->info;
333 if (metadataSize != 0) {
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700334 memcpy((uint8_t *)event + metadataOffset, halEvent->info.metadata, metadataSize);
Eric Laurent4e090692015-03-05 15:12:40 -0800335 }
336 break;
337 case RADIO_EVENT_TA:
Sanket Agarwalf639ba12015-10-12 13:05:53 -0700338 case RADIO_EVENT_EA:
Eric Laurent4e090692015-03-05 15:12:40 -0800339 case RADIO_EVENT_ANTENNA:
340 case RADIO_EVENT_CONTROL:
341 event->on = halEvent->on;
342 break;
343 case RADIO_EVENT_METADATA:
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700344 if (metadataSize != 0) {
345 memcpy((uint8_t *)event + metadataOffset, halEvent->metadata, metadataSize);
346 }
Eric Laurent4e090692015-03-05 15:12:40 -0800347 break;
348 case RADIO_EVENT_HW_FAILURE:
349 default:
350 break;
351 }
352
353 return eventMemory;
354}
355
356void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
357 {
358 sp<IMemory> eventMemory = prepareEvent(event);
359 if (eventMemory == 0) {
360 return;
361 }
362
363 AutoMutex lock(mCallbackLock);
364 mEventQueue.add(eventMemory);
365 mCallbackCond.signal();
366 ALOGV("%s DONE", __FUNCTION__);
367}
368
369
370#undef LOG_TAG
371#define LOG_TAG "RadioService::Module"
372
Eric Laurent01d267e2016-10-21 08:16:10 -0700373RadioService::Module::Module(sp<RadioInterface> hwDevice, radio_properties properties)
Eric Laurent53810822015-03-12 09:12:01 -0700374 : mHwDevice(hwDevice), mProperties(properties), mMute(true)
Eric Laurent4e090692015-03-05 15:12:40 -0800375{
376}
377
378RadioService::Module::~Module() {
Eric Laurent01d267e2016-10-21 08:16:10 -0700379 mHwDevice.clear();
Eric Laurent4e090692015-03-05 15:12:40 -0800380 mModuleClients.clear();
381}
382
383status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
384 String8 result;
385 return NO_ERROR;
386}
387
388sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client,
389 const struct radio_band_config *config,
390 bool audio)
391{
392 ALOGV("addClient() %p config %p product %s", this, config, mProperties.product);
Eric Laurent01d267e2016-10-21 08:16:10 -0700393
Eric Laurent4e090692015-03-05 15:12:40 -0800394 AutoMutex lock(mLock);
395 sp<ModuleClient> moduleClient;
396 int ret;
397
Eric Laurent01d267e2016-10-21 08:16:10 -0700398 if (mHwDevice == 0) {
399 return moduleClient;
400 }
401
Eric Laurent4e090692015-03-05 15:12:40 -0800402 for (size_t i = 0; i < mModuleClients.size(); i++) {
403 if (mModuleClients[i]->client() == client) {
404 // client already connected: reject
405 return moduleClient;
406 }
407 }
408 moduleClient = new ModuleClient(this, client, config, audio);
409
410 struct radio_hal_band_config halConfig;
411 halConfig = config->band;
412
Eric Laurent53810822015-03-12 09:12:01 -0700413 // Tuner preemption logic:
414 // There is a limited amount of tuners and a limited amount of radio audio sources per module.
415 // The minimum is one tuner and one audio source.
416 // The numbers of tuners and sources are indicated in the module properties.
417 // NOTE: current framework implementation only supports one radio audio source.
418 // It is possible to open more than one tuner at a time but only one tuner can be connected
419 // to the radio audio source (AUDIO_DEVICE_IN_FM_TUNER).
420 // The base rule is that a newly connected tuner always wins, i.e. always gets a tuner
421 // and can use the audio source if requested.
422 // If another client is preempted, it is notified by a callback with RADIO_EVENT_CONTROL
423 // indicating loss of control.
424 // - If the newly connected client requests the audio source (audio == true):
425 // - if an audio source is available
426 // no problem
427 // - if not:
428 // the oldest client in the list using audio is preempted.
429 // - If the newly connected client does not request the audio source (audio == false):
430 // - if a tuner is available
431 // no problem
432 // - if not:
433 // The oldest client not using audio is preempted first and if none is found the
434 // the oldest client using audio is preempted.
435 // Each time a tuner using the audio source is opened or closed, the audio policy manager is
436 // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
437
Eric Laurent4e090692015-03-05 15:12:40 -0800438 sp<ModuleClient> oldestTuner;
439 sp<ModuleClient> oldestAudio;
440 size_t allocatedTuners = 0;
441 size_t allocatedAudio = 0;
442 for (size_t i = 0; i < mModuleClients.size(); i++) {
443 if (mModuleClients[i]->getTuner() != NULL) {
444 if (mModuleClients[i]->audio()) {
445 if (oldestAudio == 0) {
446 oldestAudio = mModuleClients[i];
447 }
448 allocatedAudio++;
449 } else {
450 if (oldestTuner == 0) {
451 oldestTuner = mModuleClients[i];
452 }
453 allocatedTuners++;
454 }
455 }
456 }
457
Eric Laurent01d267e2016-10-21 08:16:10 -0700458 sp<TunerInterface> halTuner;
Eric Laurent53810822015-03-12 09:12:01 -0700459 sp<ModuleClient> preemtedClient;
Eric Laurent4e090692015-03-05 15:12:40 -0800460 if (audio) {
461 if (allocatedAudio >= mProperties.num_audio_sources) {
462 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700463 preemtedClient = oldestAudio;
Eric Laurent4e090692015-03-05 15:12:40 -0800464 }
465 } else {
466 if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
467 if (allocatedTuners != 0) {
468 ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700469 preemtedClient = oldestTuner;
Eric Laurent4e090692015-03-05 15:12:40 -0800470 } else {
471 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
Eric Laurent53810822015-03-12 09:12:01 -0700472 preemtedClient = oldestAudio;
Eric Laurent4e090692015-03-05 15:12:40 -0800473 }
474 }
475 }
Eric Laurent53810822015-03-12 09:12:01 -0700476 if (preemtedClient != 0) {
477 halTuner = preemtedClient->getTuner();
Eric Laurent01d267e2016-10-21 08:16:10 -0700478 sp<TunerInterface> clear;
479 preemtedClient->setTuner(clear);
480 mHwDevice->closeTuner(halTuner);
Eric Laurent53810822015-03-12 09:12:01 -0700481 if (preemtedClient->audio()) {
482 notifyDeviceConnection(false, "");
483 }
484 }
Eric Laurent4e090692015-03-05 15:12:40 -0800485
Eric Laurent01d267e2016-10-21 08:16:10 -0700486 ret = mHwDevice->openTuner(&halConfig, audio,
487 moduleClient,
488 halTuner);
Eric Laurent4e090692015-03-05 15:12:40 -0800489 if (ret == 0) {
Eric Laurent01d267e2016-10-21 08:16:10 -0700490 ALOGV("addClient() setTuner %p", halTuner.get());
Eric Laurent4e090692015-03-05 15:12:40 -0800491 moduleClient->setTuner(halTuner);
492 mModuleClients.add(moduleClient);
Eric Laurent53810822015-03-12 09:12:01 -0700493 if (audio) {
494 notifyDeviceConnection(true, "");
495 }
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700496 ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
Eric Laurent4e090692015-03-05 15:12:40 -0800497 } else {
Eric Laurentf2f79cf2015-04-23 17:10:50 -0700498 ALOGW("%s open_tuner failed with error %d", __FUNCTION__, ret);
Eric Laurent4e090692015-03-05 15:12:40 -0800499 moduleClient.clear();
500 }
501
Eric Laurent4e090692015-03-05 15:12:40 -0800502 return moduleClient;
503}
504
505void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
506 ALOGV("removeClient()");
507 AutoMutex lock(mLock);
508 int ret;
509 ssize_t index = -1;
510
511 for (size_t i = 0; i < mModuleClients.size(); i++) {
512 if (mModuleClients[i] == moduleClient) {
513 index = i;
514 break;
515 }
516 }
517 if (index == -1) {
518 return;
519 }
520
521 mModuleClients.removeAt(index);
Eric Laurent01d267e2016-10-21 08:16:10 -0700522 sp<TunerInterface> halTuner = moduleClient->getTuner();
Eric Laurent4e090692015-03-05 15:12:40 -0800523 if (halTuner == NULL) {
524 return;
525 }
526
Eric Laurent01d267e2016-10-21 08:16:10 -0700527 if (mHwDevice != 0) {
528 mHwDevice->closeTuner(halTuner);
529 }
530
Eric Laurent53810822015-03-12 09:12:01 -0700531 if (moduleClient->audio()) {
532 notifyDeviceConnection(false, "");
533 }
Eric Laurent4e090692015-03-05 15:12:40 -0800534
Eric Laurent4e090692015-03-05 15:12:40 -0800535 mMute = true;
536
537 if (mModuleClients.isEmpty()) {
538 return;
539 }
540
Eric Laurent01d267e2016-10-21 08:16:10 -0700541 if (mHwDevice == 0) {
542 return;
543 }
544
Eric Laurent53810822015-03-12 09:12:01 -0700545 // Tuner reallocation logic:
546 // When a client is removed and was controlling a tuner, this tuner will be allocated to a
547 // previously preempted client. This client will be notified by a callback with
548 // RADIO_EVENT_CONTROL indicating gain of control.
549 // - If a preempted client is waiting for an audio source and one becomes available:
550 // Allocate the tuner to the most recently added client waiting for an audio source
551 // - If not:
552 // Allocate the tuner to the most recently added client.
553 // Each time a tuner using the audio source is opened or closed, the audio policy manager is
554 // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
555
Eric Laurent4e090692015-03-05 15:12:40 -0800556 sp<ModuleClient> youngestClient;
557 sp<ModuleClient> youngestClientAudio;
558 size_t allocatedTuners = 0;
559 size_t allocatedAudio = 0;
Eric Laurent53810822015-03-12 09:12:01 -0700560 for (ssize_t i = mModuleClients.size() - 1; i >= 0; i--) {
Eric Laurent4e090692015-03-05 15:12:40 -0800561 if (mModuleClients[i]->getTuner() == NULL) {
562 if (mModuleClients[i]->audio()) {
563 if (youngestClientAudio == 0) {
564 youngestClientAudio = mModuleClients[i];
565 }
566 } else {
567 if (youngestClient == 0) {
568 youngestClient = mModuleClients[i];
569 }
570 }
571 } else {
572 if (mModuleClients[i]->audio()) {
573 allocatedAudio++;
574 } else {
575 allocatedTuners++;
576 }
577 }
578 }
579
580 ALOG_ASSERT(allocatedTuners + allocatedAudio < mProperties.num_tuners,
581 "removeClient() removed client but no tuner available");
582
583 ALOG_ASSERT(!moduleClient->audio() || allocatedAudio < mProperties.num_audio_sources,
584 "removeClient() removed audio client but no tuner with audio available");
585
586 if (allocatedAudio < mProperties.num_audio_sources && youngestClientAudio != 0) {
587 youngestClient = youngestClientAudio;
588 }
589
590 ALOG_ASSERT(youngestClient != 0, "removeClient() removed client no candidate found for tuner");
591
592 struct radio_hal_band_config halConfig = youngestClient->halConfig();
Eric Laurent01d267e2016-10-21 08:16:10 -0700593 ret = mHwDevice->openTuner(&halConfig, youngestClient->audio(),
594 moduleClient,
595 halTuner);
Eric Laurent4e090692015-03-05 15:12:40 -0800596
Eric Laurent4e090692015-03-05 15:12:40 -0800597 if (ret == 0) {
598 youngestClient->setTuner(halTuner);
Eric Laurent53810822015-03-12 09:12:01 -0700599 if (youngestClient->audio()) {
600 notifyDeviceConnection(true, "");
601 }
Eric Laurent4e090692015-03-05 15:12:40 -0800602 }
603}
604
605status_t RadioService::Module::setMute(bool mute)
606{
607 Mutex::Autolock _l(mLock);
608 if (mute != mMute) {
609 mMute = mute;
610 //TODO notifify audio policy manager of media activity on radio audio device
611 }
612 return NO_ERROR;
613}
614
615status_t RadioService::Module::getMute(bool *mute)
616{
617 Mutex::Autolock _l(mLock);
618 *mute = mMute;
619 return NO_ERROR;
620}
621
622
623const struct radio_band_config *RadioService::Module::getDefaultConfig() const
624{
625 if (mProperties.num_bands == 0) {
626 return NULL;
627 }
628 return &mProperties.bands[0];
629}
630
Eric Laurent53810822015-03-12 09:12:01 -0700631void RadioService::Module::notifyDeviceConnection(bool connected,
632 const char *address) {
633 int64_t token = IPCThreadState::self()->clearCallingIdentity();
634 AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_FM_TUNER,
635 connected ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
636 AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
637 address, kRadioTunerAudioDeviceName);
638 IPCThreadState::self()->restoreCallingIdentity(token);
639}
640
Eric Laurent4e090692015-03-05 15:12:40 -0800641#undef LOG_TAG
642#define LOG_TAG "RadioService::ModuleClient"
643
644RadioService::ModuleClient::ModuleClient(const sp<Module>& module,
645 const sp<IRadioClient>& client,
646 const struct radio_band_config *config,
647 bool audio)
Eric Laurent01d267e2016-10-21 08:16:10 -0700648 : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(0)
Eric Laurent4e090692015-03-05 15:12:40 -0800649{
650}
651
652void RadioService::ModuleClient::onFirstRef()
653{
654 mCallbackThread = new CallbackThread(this);
655 IInterface::asBinder(mClient)->linkToDeath(this);
656}
657
658RadioService::ModuleClient::~ModuleClient() {
659 if (mClient != 0) {
660 IInterface::asBinder(mClient)->unlinkToDeath(this);
661 mClient.clear();
662 }
663 if (mCallbackThread != 0) {
664 mCallbackThread->exit();
665 }
666}
667
Eric Laurent01d267e2016-10-21 08:16:10 -0700668void RadioService::ModuleClient::onEvent(radio_hal_event_t *halEvent)
669{
670 mCallbackThread->sendEvent(halEvent);
671}
672
Eric Laurent4e090692015-03-05 15:12:40 -0800673status_t RadioService::ModuleClient::dump(int fd __unused,
674 const Vector<String16>& args __unused) {
675 String8 result;
676 return NO_ERROR;
677}
678
679void RadioService::ModuleClient::detach() {
680 ALOGV("%s", __FUNCTION__);
681 sp<ModuleClient> strongMe = this;
682 {
683 AutoMutex lock(mLock);
684 if (mClient != 0) {
685 IInterface::asBinder(mClient)->unlinkToDeath(this);
686 mClient.clear();
687 }
688 }
689 sp<Module> module = mModule.promote();
690 if (module == 0) {
691 return;
692 }
693 module->removeClient(this);
694}
695
696radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
697{
698 AutoMutex lock(mLock);
699 ALOGV("%s locked", __FUNCTION__);
700 return mConfig.band;
701}
702
Eric Laurent01d267e2016-10-21 08:16:10 -0700703sp<TunerInterface>& RadioService::ModuleClient::getTuner()
Eric Laurent4e090692015-03-05 15:12:40 -0800704{
705 AutoMutex lock(mLock);
706 ALOGV("%s locked", __FUNCTION__);
707 return mTuner;
708}
709
Eric Laurent01d267e2016-10-21 08:16:10 -0700710void RadioService::ModuleClient::setTuner(sp<TunerInterface>& tuner)
Eric Laurent4e090692015-03-05 15:12:40 -0800711{
712 ALOGV("%s %p", __FUNCTION__, this);
713
714 AutoMutex lock(mLock);
715 mTuner = tuner;
716 ALOGV("%s locked", __FUNCTION__);
717
718 radio_hal_event_t event;
719 event.type = RADIO_EVENT_CONTROL;
720 event.status = 0;
Eric Laurent01d267e2016-10-21 08:16:10 -0700721 event.on = mTuner != 0;
Eric Laurent4e090692015-03-05 15:12:40 -0800722 mCallbackThread->sendEvent(&event);
723 ALOGV("%s DONE", __FUNCTION__);
724
725}
726
727status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
728{
Keun-young Park0e378542017-06-01 18:22:05 -0700729 if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
730 return PERMISSION_DENIED;
731 }
Eric Laurent4e090692015-03-05 15:12:40 -0800732 AutoMutex lock(mLock);
733 status_t status = NO_ERROR;
734 ALOGV("%s locked", __FUNCTION__);
735
Eric Laurent01d267e2016-10-21 08:16:10 -0700736 if (mTuner != 0) {
Eric Laurent4e090692015-03-05 15:12:40 -0800737 struct radio_hal_band_config halConfig;
738 halConfig = config->band;
Eric Laurent01d267e2016-10-21 08:16:10 -0700739 status = (status_t)mTuner->setConfiguration(&halConfig);
Eric Laurent4e090692015-03-05 15:12:40 -0800740 if (status == NO_ERROR) {
741 mConfig = *config;
742 }
743 } else {
744 mConfig = *config;
Aurimas Liutikas13958742016-02-18 10:02:35 -0800745 status = INVALID_OPERATION;
Eric Laurent4e090692015-03-05 15:12:40 -0800746 }
747
748 return status;
749}
750
751status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
752{
Keun-young Park0e378542017-06-01 18:22:05 -0700753 if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
754 return PERMISSION_DENIED;
755 }
Eric Laurent4e090692015-03-05 15:12:40 -0800756 AutoMutex lock(mLock);
757 status_t status = NO_ERROR;
758 ALOGV("%s locked", __FUNCTION__);
759
Eric Laurent01d267e2016-10-21 08:16:10 -0700760 if (mTuner != 0) {
Eric Laurent4e090692015-03-05 15:12:40 -0800761 struct radio_hal_band_config halConfig;
Eric Laurent01d267e2016-10-21 08:16:10 -0700762 status = (status_t)mTuner->getConfiguration(&halConfig);
Eric Laurent4e090692015-03-05 15:12:40 -0800763 if (status == NO_ERROR) {
764 mConfig.band = halConfig;
765 }
766 }
767 *config = mConfig;
768
769 return status;
770}
771
772status_t RadioService::ModuleClient::setMute(bool mute)
773{
Keun-young Park0e378542017-06-01 18:22:05 -0700774 if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
775 return PERMISSION_DENIED;
776 }
Eric Laurent4e090692015-03-05 15:12:40 -0800777 sp<Module> module;
778 {
779 Mutex::Autolock _l(mLock);
780 ALOGV("%s locked", __FUNCTION__);
Eric Laurent01d267e2016-10-21 08:16:10 -0700781 if (mTuner == 0 || !mAudio) {
Eric Laurent4e090692015-03-05 15:12:40 -0800782 return INVALID_OPERATION;
783 }
784 module = mModule.promote();
785 if (module == 0) {
786 return NO_INIT;
787 }
788 }
789 module->setMute(mute);
790 return NO_ERROR;
791}
792
793status_t RadioService::ModuleClient::getMute(bool *mute)
794{
Keun-young Park0e378542017-06-01 18:22:05 -0700795 if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
796 return PERMISSION_DENIED;
797 }
Eric Laurent4e090692015-03-05 15:12:40 -0800798 sp<Module> module;
799 {
800 Mutex::Autolock _l(mLock);
801 ALOGV("%s locked", __FUNCTION__);
802 module = mModule.promote();
803 if (module == 0) {
804 return NO_INIT;
805 }
806 }
807 return module->getMute(mute);
808}
809
810status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
811{
Keun-young Park0e378542017-06-01 18:22:05 -0700812 if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
813 return PERMISSION_DENIED;
814 }
Eric Laurent4e090692015-03-05 15:12:40 -0800815 AutoMutex lock(mLock);
816 ALOGV("%s locked", __FUNCTION__);
817 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700818 if (mTuner != 0) {
819 status = (status_t)mTuner->scan(direction, skipSubChannel);
Eric Laurent4e090692015-03-05 15:12:40 -0800820 } else {
821 status = INVALID_OPERATION;
822 }
823 return status;
824}
825
826status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
827{
Keun-young Park0e378542017-06-01 18:22:05 -0700828 if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
829 return PERMISSION_DENIED;
830 }
Eric Laurent4e090692015-03-05 15:12:40 -0800831 AutoMutex lock(mLock);
832 ALOGV("%s locked", __FUNCTION__);
833 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700834 if (mTuner != 0) {
835 status = (status_t)mTuner->step(direction, skipSubChannel);
Eric Laurent4e090692015-03-05 15:12:40 -0800836 } else {
837 status = INVALID_OPERATION;
838 }
839 return status;
840}
841
Eric Laurent01d267e2016-10-21 08:16:10 -0700842status_t RadioService::ModuleClient::tune(uint32_t channel, uint32_t subChannel)
Eric Laurent4e090692015-03-05 15:12:40 -0800843{
Keun-young Park0e378542017-06-01 18:22:05 -0700844 if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
845 return PERMISSION_DENIED;
846 }
Eric Laurent4e090692015-03-05 15:12:40 -0800847 AutoMutex lock(mLock);
848 ALOGV("%s locked", __FUNCTION__);
849 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700850 if (mTuner != 0) {
851 status = (status_t)mTuner->tune(channel, subChannel);
Eric Laurent4e090692015-03-05 15:12:40 -0800852 } else {
853 status = INVALID_OPERATION;
854 }
855 return status;
856}
857
858status_t RadioService::ModuleClient::cancel()
859{
Keun-young Park0e378542017-06-01 18:22:05 -0700860 if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
861 return PERMISSION_DENIED;
862 }
Eric Laurent4e090692015-03-05 15:12:40 -0800863 AutoMutex lock(mLock);
864 ALOGV("%s locked", __FUNCTION__);
865 status_t status;
Eric Laurent01d267e2016-10-21 08:16:10 -0700866 if (mTuner != 0) {
867 status = (status_t)mTuner->cancel();
Eric Laurent4e090692015-03-05 15:12:40 -0800868 } else {
869 status = INVALID_OPERATION;
870 }
871 return status;
872}
873
874status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
875{
Keun-young Park0e378542017-06-01 18:22:05 -0700876 if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
877 return PERMISSION_DENIED;
878 }
Eric Laurent4e090692015-03-05 15:12:40 -0800879 AutoMutex lock(mLock);
880 ALOGV("%s locked", __FUNCTION__);
881 status_t status;
882 if (mTuner != NULL) {
Eric Laurent01d267e2016-10-21 08:16:10 -0700883 status = (status_t)mTuner->getProgramInformation(info);
Eric Laurent4e090692015-03-05 15:12:40 -0800884 } else {
885 status = INVALID_OPERATION;
886 }
Eric Laurentaebf5fb2016-10-25 11:08:53 -0700887
Eric Laurent4e090692015-03-05 15:12:40 -0800888 return status;
889}
890
891status_t RadioService::ModuleClient::hasControl(bool *hasControl)
892{
Keun-young Park0e378542017-06-01 18:22:05 -0700893 if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
894 return PERMISSION_DENIED;
895 }
Eric Laurent4e090692015-03-05 15:12:40 -0800896 Mutex::Autolock lock(mLock);
897 ALOGV("%s locked", __FUNCTION__);
Eric Laurent01d267e2016-10-21 08:16:10 -0700898 *hasControl = mTuner != 0;
Eric Laurent4e090692015-03-05 15:12:40 -0800899 return NO_ERROR;
900}
901
902void RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory)
903{
904 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
905 return;
906 }
907
908 sp<IRadioClient> client;
909 {
910 AutoMutex lock(mLock);
911 ALOGV("%s locked", __FUNCTION__);
912 radio_event_t *event = (radio_event_t *)eventMemory->pointer();
913 switch (event->type) {
914 case RADIO_EVENT_CONFIG:
915 mConfig.band = event->config.band;
916 event->config.region = mConfig.region;
917 break;
918 default:
919 break;
920 }
921
922 client = mClient;
923 }
924 if (client != 0) {
925 client->onEvent(eventMemory);
926 }
927}
928
929
930void RadioService::ModuleClient::binderDied(
931 const wp<IBinder> &who __unused) {
932 ALOGW("client binder died for client %p", this);
933 detach();
934}
935
936}; // namespace android