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 <binder/PermissionCache.h>
38 #include <hardware/radio.h>
39 #include <media/AudioSystem.h>
40 #include "RadioService.h"
41 #include "RadioRegions.h"
42 
43 namespace android {
44 
45 static const char kRadioTunerAudioDeviceName[] = "Radio tuner source";
46 
47 static const String16 RADIO_PERMISSION("android.permission.ACCESS_FM_RADIO");
48 
RadioService()49 RadioService::RadioService()
50     : BnRadioService(), mNextUniqueId(1)
51 {
52     ALOGI("%s", __FUNCTION__);
53 }
54 
onFirstRef()55 void RadioService::onFirstRef()
56 {
57     ALOGI("%s", __FUNCTION__);
58 
59     sp<RadioInterface> dev = RadioInterface::connectModule(RADIO_CLASS_AM_FM);
60 
61     if (dev == 0) {
62         return;
63     }
64     struct radio_hal_properties halProperties;
65     int rc = dev->getProperties(&halProperties);
66     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);
74     convertProperties(&properties, &halProperties);
75 
76     ALOGI("loaded default module %s, ver %s, handle %d", properties.product,
77         properties.version, properties.handle);
78 
79     sp<Module> module = new Module(dev, properties);
80     mModules.add(properties.handle, module);
81 }
82 
~RadioService()83 RadioService::~RadioService()
84 {
85 }
86 
listModules(struct radio_properties * properties,uint32_t * numModules)87 status_t RadioService::listModules(struct radio_properties *properties,
88                              uint32_t *numModules)
89 {
90     if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
91         return PERMISSION_DENIED;
92     }
93     ALOGV("listModules");
94 
95     AutoMutex lock(mServiceLock);
96     if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
97         return BAD_VALUE;
98     }
99     uint32_t maxModules = *numModules;
100     *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 
attach(radio_handle_t handle,const sp<IRadioClient> & client,const struct radio_band_config * config,bool withAudio,sp<IRadio> & radio)107 status_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 {
113     if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
114         return PERMISSION_DENIED;
115     }
116     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) {
140         return NO_INIT;
141     }
142     return NO_ERROR;
143 }
144 
145 
146 static const int kDumpLockRetries = 50;
147 static const int kDumpLockSleep = 60000;
148 
tryLock(Mutex & mutex)149 static 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 
dump(int fd,const Vector<String16> & args __unused)162 status_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 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)180 status_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 
186 /* static */
convertProperties(radio_properties_t * properties,const radio_hal_properties_t * halProperties)187 void 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 
CallbackThread(const wp<ModuleClient> & moduleClient)236 RadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient)
237     : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService"))
238 {
239 }
240 
~CallbackThread()241 RadioService::CallbackThread::~CallbackThread()
242 {
243     mEventQueue.clear();
244 }
245 
onFirstRef()246 void RadioService::CallbackThread::onFirstRef()
247 {
248     run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO);
249 }
250 
threadLoop()251 bool 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 
exit()278 void RadioService::CallbackThread::exit()
279 {
280     Mutex::Autolock _l(mCallbackLock);
281     requestExit();
282     mCallbackCond.broadcast();
283 }
284 
prepareEvent(radio_hal_event_t * halEvent)285 sp<IMemory> RadioService::CallbackThread::prepareEvent(radio_hal_event_t *halEvent)
286 {
287     sp<IMemory> eventMemory;
288 
289     // 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 
296     switch (halEvent->type) {
297     case RADIO_EVENT_TUNED:
298     case RADIO_EVENT_AF_SWITCH:
299         if (radio_metadata_check(halEvent->info.metadata) == 0) {
300             metadataSize = (uint32_t)radio_metadata_get_size(halEvent->info.metadata);
301         }
302         break;
303     case RADIO_EVENT_METADATA:
304         if (radio_metadata_check(halEvent->metadata) != 0) {
305             return eventMemory;
306         }
307         metadataSize = (uint32_t)radio_metadata_get_size(halEvent->metadata);
308         break;
309     default:
310         break;
311     }
312 
313     eventMemory = mMemoryDealer->allocate(metadataOffset + metadataSize);
314     if (eventMemory == 0 || eventMemory->pointer() == NULL) {
315         eventMemory.clear();
316         return eventMemory;
317     }
318 
319     struct radio_event *event = (struct radio_event *)eventMemory->pointer();
320 
321     *(uint32_t *)((uint8_t *)event + metadataOffset - sizeof(uint32_t)) = metadataSize;
322 
323     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) {
334             memcpy((uint8_t *)event + metadataOffset, halEvent->info.metadata, metadataSize);
335         }
336         break;
337     case RADIO_EVENT_TA:
338     case RADIO_EVENT_EA:
339     case RADIO_EVENT_ANTENNA:
340     case RADIO_EVENT_CONTROL:
341         event->on = halEvent->on;
342         break;
343     case RADIO_EVENT_METADATA:
344         if (metadataSize != 0) {
345             memcpy((uint8_t *)event + metadataOffset, halEvent->metadata, metadataSize);
346         }
347         break;
348     case RADIO_EVENT_HW_FAILURE:
349     default:
350         break;
351     }
352 
353     return eventMemory;
354 }
355 
sendEvent(radio_hal_event_t * event)356 void 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 
Module(sp<RadioInterface> hwDevice,radio_properties properties)373 RadioService::Module::Module(sp<RadioInterface> hwDevice, radio_properties properties)
374  : mHwDevice(hwDevice), mProperties(properties), mMute(true)
375 {
376 }
377 
~Module()378 RadioService::Module::~Module() {
379     mHwDevice.clear();
380     mModuleClients.clear();
381 }
382 
dump(int fd __unused,const Vector<String16> & args __unused)383 status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
384     String8 result;
385     return NO_ERROR;
386 }
387 
addClient(const sp<IRadioClient> & client,const struct radio_band_config * config,bool audio)388 sp<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);
393 
394     AutoMutex lock(mLock);
395     sp<ModuleClient> moduleClient;
396     int ret;
397 
398     if (mHwDevice == 0) {
399         return moduleClient;
400     }
401 
402     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 
413     // 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 
438     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 
458     sp<TunerInterface> halTuner;
459     sp<ModuleClient> preemtedClient;
460     if (audio) {
461         if (allocatedAudio >= mProperties.num_audio_sources) {
462             ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
463             preemtedClient = oldestAudio;
464         }
465     } else {
466         if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
467             if (allocatedTuners != 0) {
468                 ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
469                 preemtedClient = oldestTuner;
470             } else {
471                 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
472                 preemtedClient = oldestAudio;
473             }
474         }
475     }
476     if (preemtedClient != 0) {
477         halTuner = preemtedClient->getTuner();
478         sp<TunerInterface> clear;
479         preemtedClient->setTuner(clear);
480         mHwDevice->closeTuner(halTuner);
481         if (preemtedClient->audio()) {
482             notifyDeviceConnection(false, "");
483         }
484     }
485 
486     ret = mHwDevice->openTuner(&halConfig, audio,
487                                moduleClient,
488                                halTuner);
489     if (ret == 0) {
490         ALOGV("addClient() setTuner %p", halTuner.get());
491         moduleClient->setTuner(halTuner);
492         mModuleClients.add(moduleClient);
493         if (audio) {
494             notifyDeviceConnection(true, "");
495         }
496         ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
497     } else {
498         ALOGW("%s open_tuner failed with error %d", __FUNCTION__, ret);
499         moduleClient.clear();
500     }
501 
502     return moduleClient;
503 }
504 
removeClient(const sp<ModuleClient> & moduleClient)505 void 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);
522     sp<TunerInterface> halTuner = moduleClient->getTuner();
523     if (halTuner == NULL) {
524         return;
525     }
526 
527     if (mHwDevice != 0) {
528         mHwDevice->closeTuner(halTuner);
529     }
530 
531     if (moduleClient->audio()) {
532         notifyDeviceConnection(false, "");
533     }
534 
535     mMute = true;
536 
537     if (mModuleClients.isEmpty()) {
538         return;
539     }
540 
541     if (mHwDevice == 0) {
542         return;
543     }
544 
545     // 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 
556     sp<ModuleClient> youngestClient;
557     sp<ModuleClient> youngestClientAudio;
558     size_t allocatedTuners = 0;
559     size_t allocatedAudio = 0;
560     for (ssize_t i = mModuleClients.size() - 1; i >= 0; i--) {
561         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();
593     ret = mHwDevice->openTuner(&halConfig, youngestClient->audio(),
594                                 moduleClient,
595                                 halTuner);
596 
597     if (ret == 0) {
598         youngestClient->setTuner(halTuner);
599         if (youngestClient->audio()) {
600             notifyDeviceConnection(true, "");
601         }
602     }
603 }
604 
setMute(bool mute)605 status_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 
getMute(bool * mute)615 status_t RadioService::Module::getMute(bool *mute)
616 {
617     Mutex::Autolock _l(mLock);
618     *mute = mMute;
619     return NO_ERROR;
620 }
621 
622 
getDefaultConfig() const623 const 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 
notifyDeviceConnection(bool connected,const char * address)631 void 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 
641 #undef LOG_TAG
642 #define LOG_TAG "RadioService::ModuleClient"
643 
ModuleClient(const sp<Module> & module,const sp<IRadioClient> & client,const struct radio_band_config * config,bool audio)644 RadioService::ModuleClient::ModuleClient(const sp<Module>& module,
645                                          const sp<IRadioClient>& client,
646                                          const struct radio_band_config *config,
647                                          bool audio)
648  : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(0)
649 {
650 }
651 
onFirstRef()652 void RadioService::ModuleClient::onFirstRef()
653 {
654     mCallbackThread = new CallbackThread(this);
655     IInterface::asBinder(mClient)->linkToDeath(this);
656 }
657 
~ModuleClient()658 RadioService::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 
onEvent(radio_hal_event_t * halEvent)668 void RadioService::ModuleClient::onEvent(radio_hal_event_t *halEvent)
669 {
670     mCallbackThread->sendEvent(halEvent);
671 }
672 
dump(int fd __unused,const Vector<String16> & args __unused)673 status_t RadioService::ModuleClient::dump(int fd __unused,
674                                              const Vector<String16>& args __unused) {
675     String8 result;
676     return NO_ERROR;
677 }
678 
detach()679 void 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 
halConfig() const696 radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
697 {
698     AutoMutex lock(mLock);
699     ALOGV("%s locked", __FUNCTION__);
700     return mConfig.band;
701 }
702 
getTuner()703 sp<TunerInterface>& RadioService::ModuleClient::getTuner()
704 {
705     AutoMutex lock(mLock);
706     ALOGV("%s locked", __FUNCTION__);
707     return mTuner;
708 }
709 
setTuner(sp<TunerInterface> & tuner)710 void RadioService::ModuleClient::setTuner(sp<TunerInterface>& tuner)
711 {
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;
721     event.on = mTuner != 0;
722     mCallbackThread->sendEvent(&event);
723     ALOGV("%s DONE", __FUNCTION__);
724 
725 }
726 
setConfiguration(const struct radio_band_config * config)727 status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
728 {
729     if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
730         return PERMISSION_DENIED;
731     }
732     AutoMutex lock(mLock);
733     status_t status = NO_ERROR;
734     ALOGV("%s locked", __FUNCTION__);
735 
736     if (mTuner != 0) {
737         struct radio_hal_band_config halConfig;
738         halConfig = config->band;
739         status = (status_t)mTuner->setConfiguration(&halConfig);
740         if (status == NO_ERROR) {
741             mConfig = *config;
742         }
743     } else {
744         mConfig = *config;
745         status = INVALID_OPERATION;
746     }
747 
748     return status;
749 }
750 
getConfiguration(struct radio_band_config * config)751 status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
752 {
753     if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
754         return PERMISSION_DENIED;
755     }
756     AutoMutex lock(mLock);
757     status_t status = NO_ERROR;
758     ALOGV("%s locked", __FUNCTION__);
759 
760     if (mTuner != 0) {
761         struct radio_hal_band_config halConfig;
762         status = (status_t)mTuner->getConfiguration(&halConfig);
763         if (status == NO_ERROR) {
764             mConfig.band = halConfig;
765         }
766     }
767     *config = mConfig;
768 
769     return status;
770 }
771 
setMute(bool mute)772 status_t RadioService::ModuleClient::setMute(bool mute)
773 {
774     if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
775         return PERMISSION_DENIED;
776     }
777     sp<Module> module;
778     {
779         Mutex::Autolock _l(mLock);
780         ALOGV("%s locked", __FUNCTION__);
781         if (mTuner == 0 || !mAudio) {
782             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 
getMute(bool * mute)793 status_t RadioService::ModuleClient::getMute(bool *mute)
794 {
795     if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
796         return PERMISSION_DENIED;
797     }
798     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 
scan(radio_direction_t direction,bool skipSubChannel)810 status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
811 {
812     if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
813         return PERMISSION_DENIED;
814     }
815     AutoMutex lock(mLock);
816     ALOGV("%s locked", __FUNCTION__);
817     status_t status;
818     if (mTuner != 0) {
819         status = (status_t)mTuner->scan(direction, skipSubChannel);
820     } else {
821         status = INVALID_OPERATION;
822     }
823     return status;
824 }
825 
step(radio_direction_t direction,bool skipSubChannel)826 status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
827 {
828     if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
829         return PERMISSION_DENIED;
830     }
831     AutoMutex lock(mLock);
832     ALOGV("%s locked", __FUNCTION__);
833     status_t status;
834     if (mTuner != 0) {
835         status = (status_t)mTuner->step(direction, skipSubChannel);
836     } else {
837         status = INVALID_OPERATION;
838     }
839     return status;
840 }
841 
tune(uint32_t channel,uint32_t subChannel)842 status_t RadioService::ModuleClient::tune(uint32_t channel, uint32_t subChannel)
843 {
844     if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
845         return PERMISSION_DENIED;
846     }
847     AutoMutex lock(mLock);
848     ALOGV("%s locked", __FUNCTION__);
849     status_t status;
850     if (mTuner != 0) {
851         status = (status_t)mTuner->tune(channel, subChannel);
852     } else {
853         status = INVALID_OPERATION;
854     }
855     return status;
856 }
857 
cancel()858 status_t RadioService::ModuleClient::cancel()
859 {
860     if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
861         return PERMISSION_DENIED;
862     }
863     AutoMutex lock(mLock);
864     ALOGV("%s locked", __FUNCTION__);
865     status_t status;
866     if (mTuner != 0) {
867         status = (status_t)mTuner->cancel();
868     } else {
869         status = INVALID_OPERATION;
870     }
871     return status;
872 }
873 
getProgramInformation(struct radio_program_info * info)874 status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
875 {
876     if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
877         return PERMISSION_DENIED;
878     }
879     AutoMutex lock(mLock);
880     ALOGV("%s locked", __FUNCTION__);
881     status_t status;
882     if (mTuner != NULL) {
883         status = (status_t)mTuner->getProgramInformation(info);
884     } else {
885         status = INVALID_OPERATION;
886     }
887 
888     return status;
889 }
890 
hasControl(bool * hasControl)891 status_t RadioService::ModuleClient::hasControl(bool *hasControl)
892 {
893     if (!PermissionCache::checkCallingPermission(RADIO_PERMISSION)) {
894         return PERMISSION_DENIED;
895     }
896     Mutex::Autolock lock(mLock);
897     ALOGV("%s locked", __FUNCTION__);
898     *hasControl = mTuner != 0;
899     return NO_ERROR;
900 }
901 
onCallbackEvent(const sp<IMemory> & eventMemory)902 void 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 
binderDied(const wp<IBinder> & who __unused)930 void 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
937