1 /*
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
25 #include <system/audio.h>
26 #include <system/audio_policy.h>
27 #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>
37 #include <hardware/radio.h>
38 #include <media/AudioSystem.h>
39 #include "RadioService.h"
40 #include "RadioRegions.h"
41
42 namespace android {
43
44 static const char kRadioTunerAudioDeviceName[] = "Radio tuner source";
45
RadioService()46 RadioService::RadioService()
47 : BnRadioService(), mNextUniqueId(1)
48 {
49 ALOGI("%s", __FUNCTION__);
50 }
51
onFirstRef()52 void RadioService::onFirstRef()
53 {
54 const hw_module_t *mod;
55 int rc;
56 struct radio_hw_device *dev;
57
58 ALOGI("%s", __FUNCTION__);
59
60 rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, RADIO_HARDWARE_MODULE_ID_FM, &mod);
61 if (rc != 0) {
62 ALOGE("couldn't load radio module %s.%s (%s)",
63 RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
64 return;
65 }
66 rc = radio_hw_device_open(mod, &dev);
67 if (rc != 0) {
68 ALOGE("couldn't open radio hw device in %s.%s (%s)",
69 RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
70 return;
71 }
72 if (dev->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
73 ALOGE("wrong radio hw device version %04x", dev->common.version);
74 return;
75 }
76
77 struct radio_hal_properties halProperties;
78 rc = dev->get_properties(dev, &halProperties);
79 if (rc != 0) {
80 ALOGE("could not read implementation properties");
81 return;
82 }
83
84 radio_properties_t properties;
85 properties.handle =
86 (radio_handle_t)android_atomic_inc(&mNextUniqueId);
87
88 ALOGI("loaded default module %s, handle %d", properties.product, properties.handle);
89
90 convertProperties(&properties, &halProperties);
91 sp<Module> module = new Module(dev, properties);
92 mModules.add(properties.handle, module);
93 }
94
~RadioService()95 RadioService::~RadioService()
96 {
97 for (size_t i = 0; i < mModules.size(); i++) {
98 radio_hw_device_close(mModules.valueAt(i)->hwDevice());
99 }
100 }
101
listModules(struct radio_properties * properties,uint32_t * numModules)102 status_t RadioService::listModules(struct radio_properties *properties,
103 uint32_t *numModules)
104 {
105 ALOGV("listModules");
106
107 AutoMutex lock(mServiceLock);
108 if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
109 return BAD_VALUE;
110 }
111 size_t maxModules = *numModules;
112 *numModules = mModules.size();
113 for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
114 properties[i] = mModules.valueAt(i)->properties();
115 }
116 return NO_ERROR;
117 }
118
attach(radio_handle_t handle,const sp<IRadioClient> & client,const struct radio_band_config * config,bool withAudio,sp<IRadio> & radio)119 status_t RadioService::attach(radio_handle_t handle,
120 const sp<IRadioClient>& client,
121 const struct radio_band_config *config,
122 bool withAudio,
123 sp<IRadio>& radio)
124 {
125 ALOGV("%s %d config %p withAudio %d", __FUNCTION__, handle, config, withAudio);
126
127 AutoMutex lock(mServiceLock);
128 radio.clear();
129 if (client == 0) {
130 return BAD_VALUE;
131 }
132 ssize_t index = mModules.indexOfKey(handle);
133 if (index < 0) {
134 return BAD_VALUE;
135 }
136 sp<Module> module = mModules.valueAt(index);
137
138 if (config == NULL) {
139 config = module->getDefaultConfig();
140 if (config == NULL) {
141 return INVALID_OPERATION;
142 }
143 }
144 ALOGV("%s region %d type %d", __FUNCTION__, config->region, config->band.type);
145
146 radio = module->addClient(client, config, withAudio);
147
148 if (radio == 0) {
149 return NO_INIT;
150 }
151 return NO_ERROR;
152 }
153
154
155 static const int kDumpLockRetries = 50;
156 static const int kDumpLockSleep = 60000;
157
tryLock(Mutex & mutex)158 static bool tryLock(Mutex& mutex)
159 {
160 bool locked = false;
161 for (int i = 0; i < kDumpLockRetries; ++i) {
162 if (mutex.tryLock() == NO_ERROR) {
163 locked = true;
164 break;
165 }
166 usleep(kDumpLockSleep);
167 }
168 return locked;
169 }
170
dump(int fd,const Vector<String16> & args __unused)171 status_t RadioService::dump(int fd, const Vector<String16>& args __unused) {
172 String8 result;
173 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
174 result.appendFormat("Permission Denial: can't dump RadioService");
175 write(fd, result.string(), result.size());
176 } else {
177 bool locked = tryLock(mServiceLock);
178 // failed to lock - RadioService is probably deadlocked
179 if (!locked) {
180 result.append("RadioService may be deadlocked\n");
181 write(fd, result.string(), result.size());
182 }
183
184 if (locked) mServiceLock.unlock();
185 }
186 return NO_ERROR;
187 }
188
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)189 status_t RadioService::onTransact(
190 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
191 return BnRadioService::onTransact(code, data, reply, flags);
192 }
193
194
195 // static
callback(radio_hal_event_t * halEvent,void * cookie)196 void RadioService::callback(radio_hal_event_t *halEvent, void *cookie)
197 {
198 CallbackThread *callbackThread = (CallbackThread *)cookie;
199 if (callbackThread == NULL) {
200 return;
201 }
202 callbackThread->sendEvent(halEvent);
203 }
204
205 /* static */
convertProperties(radio_properties_t * properties,const radio_hal_properties_t * halProperties)206 void RadioService::convertProperties(radio_properties_t *properties,
207 const radio_hal_properties_t *halProperties)
208 {
209 memset(properties, 0, sizeof(struct radio_properties));
210 properties->class_id = halProperties->class_id;
211 strlcpy(properties->implementor, halProperties->implementor,
212 RADIO_STRING_LEN_MAX);
213 strlcpy(properties->product, halProperties->product,
214 RADIO_STRING_LEN_MAX);
215 strlcpy(properties->version, halProperties->version,
216 RADIO_STRING_LEN_MAX);
217 strlcpy(properties->serial, halProperties->serial,
218 RADIO_STRING_LEN_MAX);
219 properties->num_tuners = halProperties->num_tuners;
220 properties->num_audio_sources = halProperties->num_audio_sources;
221 properties->supports_capture = halProperties->supports_capture;
222
223 for (size_t i = 0; i < ARRAY_SIZE(sKnownRegionConfigs); i++) {
224 const radio_hal_band_config_t *band = &sKnownRegionConfigs[i].band;
225 size_t j;
226 for (j = 0; j < halProperties->num_bands; j++) {
227 const radio_hal_band_config_t *halBand = &halProperties->bands[j];
228 size_t k;
229 if (band->type != halBand->type) continue;
230 if (band->lower_limit < halBand->lower_limit) continue;
231 if (band->upper_limit > halBand->upper_limit) continue;
232 for (k = 0; k < halBand->num_spacings; k++) {
233 if (band->spacings[0] == halBand->spacings[k]) break;
234 }
235 if (k == halBand->num_spacings) continue;
236 if (band->type == RADIO_BAND_AM) break;
237 if ((band->fm.deemphasis & halBand->fm.deemphasis) == 0) continue;
238 if (halBand->fm.rds == 0) break;
239 if ((band->fm.rds & halBand->fm.rds) != 0) break;
240 }
241 if (j == halProperties->num_bands) continue;
242
243 ALOGI("convertProperties() Adding band type %d region %d",
244 sKnownRegionConfigs[i].band.type , sKnownRegionConfigs[i].region);
245
246 memcpy(&properties->bands[properties->num_bands++],
247 &sKnownRegionConfigs[i],
248 sizeof(radio_band_config_t));
249 }
250 }
251
252 #undef LOG_TAG
253 #define LOG_TAG "RadioService::CallbackThread"
254
CallbackThread(const wp<ModuleClient> & moduleClient)255 RadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient)
256 : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService"))
257 {
258 }
259
~CallbackThread()260 RadioService::CallbackThread::~CallbackThread()
261 {
262 mEventQueue.clear();
263 }
264
onFirstRef()265 void RadioService::CallbackThread::onFirstRef()
266 {
267 run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO);
268 }
269
threadLoop()270 bool RadioService::CallbackThread::threadLoop()
271 {
272 while (!exitPending()) {
273 sp<IMemory> eventMemory;
274 sp<ModuleClient> moduleClient;
275 {
276 Mutex::Autolock _l(mCallbackLock);
277 while (mEventQueue.isEmpty() && !exitPending()) {
278 ALOGV("CallbackThread::threadLoop() sleep");
279 mCallbackCond.wait(mCallbackLock);
280 ALOGV("CallbackThread::threadLoop() wake up");
281 }
282 if (exitPending()) {
283 break;
284 }
285 eventMemory = mEventQueue[0];
286 mEventQueue.removeAt(0);
287 moduleClient = mModuleClient.promote();
288 }
289 if (moduleClient != 0) {
290 moduleClient->onCallbackEvent(eventMemory);
291 eventMemory.clear();
292 }
293 }
294 return false;
295 }
296
exit()297 void RadioService::CallbackThread::exit()
298 {
299 Mutex::Autolock _l(mCallbackLock);
300 requestExit();
301 mCallbackCond.broadcast();
302 }
303
prepareEvent(radio_hal_event_t * halEvent)304 sp<IMemory> RadioService::CallbackThread::prepareEvent(radio_hal_event_t *halEvent)
305 {
306 sp<IMemory> eventMemory;
307
308 size_t headerSize =
309 (sizeof(struct radio_event) + sizeof(unsigned int) - 1) /sizeof(unsigned int);
310 size_t metadataSize = 0;
311 switch (halEvent->type) {
312 case RADIO_EVENT_TUNED:
313 case RADIO_EVENT_AF_SWITCH:
314 if (radio_metadata_check(halEvent->info.metadata) == 0) {
315 metadataSize = radio_metadata_get_size(halEvent->info.metadata);
316 }
317 break;
318 case RADIO_EVENT_METADATA:
319 if (radio_metadata_check(halEvent->metadata) != 0) {
320 return eventMemory;
321 }
322 metadataSize = radio_metadata_get_size(halEvent->metadata);
323 break;
324 default:
325 break;
326 }
327 size_t size = headerSize + metadataSize;
328 eventMemory = mMemoryDealer->allocate(size);
329 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
330 eventMemory.clear();
331 return eventMemory;
332 }
333 struct radio_event *event = (struct radio_event *)eventMemory->pointer();
334 event->type = halEvent->type;
335 event->status = halEvent->status;
336
337 switch (event->type) {
338 case RADIO_EVENT_CONFIG:
339 event->config.band = halEvent->config;
340 break;
341 case RADIO_EVENT_TUNED:
342 case RADIO_EVENT_AF_SWITCH:
343 event->info = halEvent->info;
344 if (metadataSize != 0) {
345 memcpy((char *)event + headerSize, halEvent->info.metadata, metadataSize);
346 // replace meta data pointer by offset while in shared memory so that receiving side
347 // can restore the pointer in destination process.
348 event->info.metadata = (radio_metadata_t *)headerSize;
349 }
350 break;
351 case RADIO_EVENT_TA:
352 case RADIO_EVENT_EA:
353 case RADIO_EVENT_ANTENNA:
354 case RADIO_EVENT_CONTROL:
355 event->on = halEvent->on;
356 break;
357 case RADIO_EVENT_METADATA:
358 memcpy((char *)event + headerSize, halEvent->metadata, metadataSize);
359 // replace meta data pointer by offset while in shared memory so that receiving side
360 // can restore the pointer in destination process.
361 event->metadata = (radio_metadata_t *)headerSize;
362 break;
363 case RADIO_EVENT_HW_FAILURE:
364 default:
365 break;
366 }
367
368 return eventMemory;
369 }
370
sendEvent(radio_hal_event_t * event)371 void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
372 {
373 sp<IMemory> eventMemory = prepareEvent(event);
374 if (eventMemory == 0) {
375 return;
376 }
377
378 AutoMutex lock(mCallbackLock);
379 mEventQueue.add(eventMemory);
380 mCallbackCond.signal();
381 ALOGV("%s DONE", __FUNCTION__);
382 }
383
384
385 #undef LOG_TAG
386 #define LOG_TAG "RadioService::Module"
387
Module(radio_hw_device * hwDevice,radio_properties properties)388 RadioService::Module::Module(radio_hw_device* hwDevice, radio_properties properties)
389 : mHwDevice(hwDevice), mProperties(properties), mMute(true)
390 {
391 }
392
~Module()393 RadioService::Module::~Module() {
394 mModuleClients.clear();
395 }
396
dump(int fd __unused,const Vector<String16> & args __unused)397 status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
398 String8 result;
399 return NO_ERROR;
400 }
401
addClient(const sp<IRadioClient> & client,const struct radio_band_config * config,bool audio)402 sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client,
403 const struct radio_band_config *config,
404 bool audio)
405 {
406 ALOGV("addClient() %p config %p product %s", this, config, mProperties.product);
407 AutoMutex lock(mLock);
408 sp<ModuleClient> moduleClient;
409 int ret;
410
411 for (size_t i = 0; i < mModuleClients.size(); i++) {
412 if (mModuleClients[i]->client() == client) {
413 // client already connected: reject
414 return moduleClient;
415 }
416 }
417 moduleClient = new ModuleClient(this, client, config, audio);
418
419 struct radio_hal_band_config halConfig;
420 halConfig = config->band;
421
422 // Tuner preemption logic:
423 // There is a limited amount of tuners and a limited amount of radio audio sources per module.
424 // The minimum is one tuner and one audio source.
425 // The numbers of tuners and sources are indicated in the module properties.
426 // NOTE: current framework implementation only supports one radio audio source.
427 // It is possible to open more than one tuner at a time but only one tuner can be connected
428 // to the radio audio source (AUDIO_DEVICE_IN_FM_TUNER).
429 // The base rule is that a newly connected tuner always wins, i.e. always gets a tuner
430 // and can use the audio source if requested.
431 // If another client is preempted, it is notified by a callback with RADIO_EVENT_CONTROL
432 // indicating loss of control.
433 // - If the newly connected client requests the audio source (audio == true):
434 // - if an audio source is available
435 // no problem
436 // - if not:
437 // the oldest client in the list using audio is preempted.
438 // - If the newly connected client does not request the audio source (audio == false):
439 // - if a tuner is available
440 // no problem
441 // - if not:
442 // The oldest client not using audio is preempted first and if none is found the
443 // the oldest client using audio is preempted.
444 // Each time a tuner using the audio source is opened or closed, the audio policy manager is
445 // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
446
447 sp<ModuleClient> oldestTuner;
448 sp<ModuleClient> oldestAudio;
449 size_t allocatedTuners = 0;
450 size_t allocatedAudio = 0;
451 for (size_t i = 0; i < mModuleClients.size(); i++) {
452 if (mModuleClients[i]->getTuner() != NULL) {
453 if (mModuleClients[i]->audio()) {
454 if (oldestAudio == 0) {
455 oldestAudio = mModuleClients[i];
456 }
457 allocatedAudio++;
458 } else {
459 if (oldestTuner == 0) {
460 oldestTuner = mModuleClients[i];
461 }
462 allocatedTuners++;
463 }
464 }
465 }
466
467 const struct radio_tuner *halTuner;
468 sp<ModuleClient> preemtedClient;
469 if (audio) {
470 if (allocatedAudio >= mProperties.num_audio_sources) {
471 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
472 preemtedClient = oldestAudio;
473 }
474 } else {
475 if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
476 if (allocatedTuners != 0) {
477 ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
478 preemtedClient = oldestTuner;
479 } else {
480 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
481 preemtedClient = oldestAudio;
482 }
483 }
484 }
485 if (preemtedClient != 0) {
486 halTuner = preemtedClient->getTuner();
487 preemtedClient->setTuner(NULL);
488 mHwDevice->close_tuner(mHwDevice, halTuner);
489 if (preemtedClient->audio()) {
490 notifyDeviceConnection(false, "");
491 }
492 }
493
494 ret = mHwDevice->open_tuner(mHwDevice, &halConfig, audio,
495 RadioService::callback, moduleClient->callbackThread().get(),
496 &halTuner);
497 if (ret == 0) {
498 ALOGV("addClient() setTuner %p", halTuner);
499 moduleClient->setTuner(halTuner);
500 mModuleClients.add(moduleClient);
501 if (audio) {
502 notifyDeviceConnection(true, "");
503 }
504 ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
505 } else {
506 ALOGW("%s open_tuner failed with error %d", __FUNCTION__, ret);
507 moduleClient.clear();
508 }
509
510 return moduleClient;
511 }
512
removeClient(const sp<ModuleClient> & moduleClient)513 void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
514 ALOGV("removeClient()");
515 AutoMutex lock(mLock);
516 int ret;
517 ssize_t index = -1;
518
519 for (size_t i = 0; i < mModuleClients.size(); i++) {
520 if (mModuleClients[i] == moduleClient) {
521 index = i;
522 break;
523 }
524 }
525 if (index == -1) {
526 return;
527 }
528
529 mModuleClients.removeAt(index);
530 const struct radio_tuner *halTuner = moduleClient->getTuner();
531 if (halTuner == NULL) {
532 return;
533 }
534
535 mHwDevice->close_tuner(mHwDevice, halTuner);
536 if (moduleClient->audio()) {
537 notifyDeviceConnection(false, "");
538 }
539
540 mMute = true;
541
542 if (mModuleClients.isEmpty()) {
543 return;
544 }
545
546 // Tuner reallocation logic:
547 // When a client is removed and was controlling a tuner, this tuner will be allocated to a
548 // previously preempted client. This client will be notified by a callback with
549 // RADIO_EVENT_CONTROL indicating gain of control.
550 // - If a preempted client is waiting for an audio source and one becomes available:
551 // Allocate the tuner to the most recently added client waiting for an audio source
552 // - If not:
553 // Allocate the tuner to the most recently added client.
554 // Each time a tuner using the audio source is opened or closed, the audio policy manager is
555 // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
556
557 sp<ModuleClient> youngestClient;
558 sp<ModuleClient> youngestClientAudio;
559 size_t allocatedTuners = 0;
560 size_t allocatedAudio = 0;
561 for (ssize_t i = mModuleClients.size() - 1; i >= 0; i--) {
562 if (mModuleClients[i]->getTuner() == NULL) {
563 if (mModuleClients[i]->audio()) {
564 if (youngestClientAudio == 0) {
565 youngestClientAudio = mModuleClients[i];
566 }
567 } else {
568 if (youngestClient == 0) {
569 youngestClient = mModuleClients[i];
570 }
571 }
572 } else {
573 if (mModuleClients[i]->audio()) {
574 allocatedAudio++;
575 } else {
576 allocatedTuners++;
577 }
578 }
579 }
580
581 ALOG_ASSERT(allocatedTuners + allocatedAudio < mProperties.num_tuners,
582 "removeClient() removed client but no tuner available");
583
584 ALOG_ASSERT(!moduleClient->audio() || allocatedAudio < mProperties.num_audio_sources,
585 "removeClient() removed audio client but no tuner with audio available");
586
587 if (allocatedAudio < mProperties.num_audio_sources && youngestClientAudio != 0) {
588 youngestClient = youngestClientAudio;
589 }
590
591 ALOG_ASSERT(youngestClient != 0, "removeClient() removed client no candidate found for tuner");
592
593 struct radio_hal_band_config halConfig = youngestClient->halConfig();
594 ret = mHwDevice->open_tuner(mHwDevice, &halConfig, youngestClient->audio(),
595 RadioService::callback, moduleClient->callbackThread().get(),
596 &halTuner);
597
598 if (ret == 0) {
599 youngestClient->setTuner(halTuner);
600 if (youngestClient->audio()) {
601 notifyDeviceConnection(true, "");
602 }
603 }
604 }
605
setMute(bool mute)606 status_t RadioService::Module::setMute(bool mute)
607 {
608 Mutex::Autolock _l(mLock);
609 if (mute != mMute) {
610 mMute = mute;
611 //TODO notifify audio policy manager of media activity on radio audio device
612 }
613 return NO_ERROR;
614 }
615
getMute(bool * mute)616 status_t RadioService::Module::getMute(bool *mute)
617 {
618 Mutex::Autolock _l(mLock);
619 *mute = mMute;
620 return NO_ERROR;
621 }
622
623
getDefaultConfig() const624 const struct radio_band_config *RadioService::Module::getDefaultConfig() const
625 {
626 if (mProperties.num_bands == 0) {
627 return NULL;
628 }
629 return &mProperties.bands[0];
630 }
631
notifyDeviceConnection(bool connected,const char * address)632 void RadioService::Module::notifyDeviceConnection(bool connected,
633 const char *address) {
634 int64_t token = IPCThreadState::self()->clearCallingIdentity();
635 AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_FM_TUNER,
636 connected ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
637 AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
638 address, kRadioTunerAudioDeviceName);
639 IPCThreadState::self()->restoreCallingIdentity(token);
640 }
641
642 #undef LOG_TAG
643 #define LOG_TAG "RadioService::ModuleClient"
644
ModuleClient(const sp<Module> & module,const sp<IRadioClient> & client,const struct radio_band_config * config,bool audio)645 RadioService::ModuleClient::ModuleClient(const sp<Module>& module,
646 const sp<IRadioClient>& client,
647 const struct radio_band_config *config,
648 bool audio)
649 : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(NULL)
650 {
651 }
652
onFirstRef()653 void RadioService::ModuleClient::onFirstRef()
654 {
655 mCallbackThread = new CallbackThread(this);
656 IInterface::asBinder(mClient)->linkToDeath(this);
657 }
658
~ModuleClient()659 RadioService::ModuleClient::~ModuleClient() {
660 if (mClient != 0) {
661 IInterface::asBinder(mClient)->unlinkToDeath(this);
662 mClient.clear();
663 }
664 if (mCallbackThread != 0) {
665 mCallbackThread->exit();
666 }
667 }
668
dump(int fd __unused,const Vector<String16> & args __unused)669 status_t RadioService::ModuleClient::dump(int fd __unused,
670 const Vector<String16>& args __unused) {
671 String8 result;
672 return NO_ERROR;
673 }
674
detach()675 void RadioService::ModuleClient::detach() {
676 ALOGV("%s", __FUNCTION__);
677 sp<ModuleClient> strongMe = this;
678 {
679 AutoMutex lock(mLock);
680 if (mClient != 0) {
681 IInterface::asBinder(mClient)->unlinkToDeath(this);
682 mClient.clear();
683 }
684 }
685 sp<Module> module = mModule.promote();
686 if (module == 0) {
687 return;
688 }
689 module->removeClient(this);
690 }
691
halConfig() const692 radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
693 {
694 AutoMutex lock(mLock);
695 ALOGV("%s locked", __FUNCTION__);
696 return mConfig.band;
697 }
698
getTuner() const699 const struct radio_tuner *RadioService::ModuleClient::getTuner() const
700 {
701 AutoMutex lock(mLock);
702 ALOGV("%s locked", __FUNCTION__);
703 return mTuner;
704 }
705
setTuner(const struct radio_tuner * tuner)706 void RadioService::ModuleClient::setTuner(const struct radio_tuner *tuner)
707 {
708 ALOGV("%s %p", __FUNCTION__, this);
709
710 AutoMutex lock(mLock);
711 mTuner = tuner;
712 ALOGV("%s locked", __FUNCTION__);
713
714 radio_hal_event_t event;
715 event.type = RADIO_EVENT_CONTROL;
716 event.status = 0;
717 event.on = mTuner != NULL;
718 mCallbackThread->sendEvent(&event);
719 ALOGV("%s DONE", __FUNCTION__);
720
721 }
722
setConfiguration(const struct radio_band_config * config)723 status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
724 {
725 AutoMutex lock(mLock);
726 status_t status = NO_ERROR;
727 ALOGV("%s locked", __FUNCTION__);
728
729 if (mTuner != NULL) {
730 struct radio_hal_band_config halConfig;
731 halConfig = config->band;
732 status = (status_t)mTuner->set_configuration(mTuner, &halConfig);
733 if (status == NO_ERROR) {
734 mConfig = *config;
735 }
736 } else {
737 mConfig = *config;
738 status = INVALID_OPERATION;
739 }
740
741 return status;
742 }
743
getConfiguration(struct radio_band_config * config)744 status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
745 {
746 AutoMutex lock(mLock);
747 status_t status = NO_ERROR;
748 ALOGV("%s locked", __FUNCTION__);
749
750 if (mTuner != NULL) {
751 struct radio_hal_band_config halConfig;
752 status = (status_t)mTuner->get_configuration(mTuner, &halConfig);
753 if (status == NO_ERROR) {
754 mConfig.band = halConfig;
755 }
756 }
757 *config = mConfig;
758
759 return status;
760 }
761
setMute(bool mute)762 status_t RadioService::ModuleClient::setMute(bool mute)
763 {
764 sp<Module> module;
765 {
766 Mutex::Autolock _l(mLock);
767 ALOGV("%s locked", __FUNCTION__);
768 if (mTuner == NULL || !mAudio) {
769 return INVALID_OPERATION;
770 }
771 module = mModule.promote();
772 if (module == 0) {
773 return NO_INIT;
774 }
775 }
776 module->setMute(mute);
777 return NO_ERROR;
778 }
779
getMute(bool * mute)780 status_t RadioService::ModuleClient::getMute(bool *mute)
781 {
782 sp<Module> module;
783 {
784 Mutex::Autolock _l(mLock);
785 ALOGV("%s locked", __FUNCTION__);
786 module = mModule.promote();
787 if (module == 0) {
788 return NO_INIT;
789 }
790 }
791 return module->getMute(mute);
792 }
793
scan(radio_direction_t direction,bool skipSubChannel)794 status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
795 {
796 AutoMutex lock(mLock);
797 ALOGV("%s locked", __FUNCTION__);
798 status_t status;
799 if (mTuner != NULL) {
800 status = (status_t)mTuner->scan(mTuner, direction, skipSubChannel);
801 } else {
802 status = INVALID_OPERATION;
803 }
804 return status;
805 }
806
step(radio_direction_t direction,bool skipSubChannel)807 status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
808 {
809 AutoMutex lock(mLock);
810 ALOGV("%s locked", __FUNCTION__);
811 status_t status;
812 if (mTuner != NULL) {
813 status = (status_t)mTuner->step(mTuner, direction, skipSubChannel);
814 } else {
815 status = INVALID_OPERATION;
816 }
817 return status;
818 }
819
tune(unsigned int channel,unsigned int subChannel)820 status_t RadioService::ModuleClient::tune(unsigned int channel, unsigned int subChannel)
821 {
822 AutoMutex lock(mLock);
823 ALOGV("%s locked", __FUNCTION__);
824 status_t status;
825 if (mTuner != NULL) {
826 status = (status_t)mTuner->tune(mTuner, channel, subChannel);
827 } else {
828 status = INVALID_OPERATION;
829 }
830 return status;
831 }
832
cancel()833 status_t RadioService::ModuleClient::cancel()
834 {
835 AutoMutex lock(mLock);
836 ALOGV("%s locked", __FUNCTION__);
837 status_t status;
838 if (mTuner != NULL) {
839 status = (status_t)mTuner->cancel(mTuner);
840 } else {
841 status = INVALID_OPERATION;
842 }
843 return status;
844 }
845
getProgramInformation(struct radio_program_info * info)846 status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
847 {
848 AutoMutex lock(mLock);
849 ALOGV("%s locked", __FUNCTION__);
850 status_t status;
851 if (mTuner != NULL) {
852 status = (status_t)mTuner->get_program_information(mTuner, info);
853 } else {
854 status = INVALID_OPERATION;
855 }
856 return status;
857 }
858
hasControl(bool * hasControl)859 status_t RadioService::ModuleClient::hasControl(bool *hasControl)
860 {
861 Mutex::Autolock lock(mLock);
862 ALOGV("%s locked", __FUNCTION__);
863 *hasControl = mTuner != NULL;
864 return NO_ERROR;
865 }
866
onCallbackEvent(const sp<IMemory> & eventMemory)867 void RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory)
868 {
869 if (eventMemory == 0 || eventMemory->pointer() == NULL) {
870 return;
871 }
872
873 sp<IRadioClient> client;
874 {
875 AutoMutex lock(mLock);
876 ALOGV("%s locked", __FUNCTION__);
877 radio_event_t *event = (radio_event_t *)eventMemory->pointer();
878 switch (event->type) {
879 case RADIO_EVENT_CONFIG:
880 mConfig.band = event->config.band;
881 event->config.region = mConfig.region;
882 break;
883 default:
884 break;
885 }
886
887 client = mClient;
888 }
889 if (client != 0) {
890 client->onEvent(eventMemory);
891 }
892 }
893
894
binderDied(const wp<IBinder> & who __unused)895 void RadioService::ModuleClient::binderDied(
896 const wp<IBinder> &who __unused) {
897 ALOGW("client binder died for client %p", this);
898 detach();
899 }
900
901 }; // namespace android
902