• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ANTENNA:
353     case RADIO_EVENT_CONTROL:
354         event->on = halEvent->on;
355         break;
356     case RADIO_EVENT_METADATA:
357         memcpy((char *)event + headerSize, halEvent->metadata, metadataSize);
358         // replace meta data pointer by offset while in shared memory so that receiving side
359         // can restore the pointer in destination process.
360         event->metadata = (radio_metadata_t *)headerSize;
361         break;
362     case RADIO_EVENT_HW_FAILURE:
363     default:
364         break;
365     }
366 
367     return eventMemory;
368 }
369 
sendEvent(radio_hal_event_t * event)370 void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
371  {
372      sp<IMemory> eventMemory = prepareEvent(event);
373      if (eventMemory == 0) {
374          return;
375      }
376 
377      AutoMutex lock(mCallbackLock);
378      mEventQueue.add(eventMemory);
379      mCallbackCond.signal();
380      ALOGV("%s DONE", __FUNCTION__);
381 }
382 
383 
384 #undef LOG_TAG
385 #define LOG_TAG "RadioService::Module"
386 
Module(radio_hw_device * hwDevice,radio_properties properties)387 RadioService::Module::Module(radio_hw_device* hwDevice, radio_properties properties)
388  : mHwDevice(hwDevice), mProperties(properties), mMute(true)
389 {
390 }
391 
~Module()392 RadioService::Module::~Module() {
393     mModuleClients.clear();
394 }
395 
dump(int fd __unused,const Vector<String16> & args __unused)396 status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
397     String8 result;
398     return NO_ERROR;
399 }
400 
addClient(const sp<IRadioClient> & client,const struct radio_band_config * config,bool audio)401 sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client,
402                                     const struct radio_band_config *config,
403                                     bool audio)
404 {
405     ALOGV("addClient() %p config %p product %s", this, config, mProperties.product);
406     AutoMutex lock(mLock);
407     sp<ModuleClient> moduleClient;
408     int ret;
409 
410     for (size_t i = 0; i < mModuleClients.size(); i++) {
411         if (mModuleClients[i]->client() == client) {
412             // client already connected: reject
413             return moduleClient;
414         }
415     }
416     moduleClient = new ModuleClient(this, client, config, audio);
417 
418     struct radio_hal_band_config halConfig;
419     halConfig = config->band;
420 
421     // Tuner preemption logic:
422     // There is a limited amount of tuners and a limited amount of radio audio sources per module.
423     // The minimum is one tuner and one audio source.
424     // The numbers of tuners and sources are indicated in the module properties.
425     // NOTE: current framework implementation only supports one radio audio source.
426     // It is possible to open more than one tuner at a time but only one tuner can be connected
427     // to the radio audio source (AUDIO_DEVICE_IN_FM_TUNER).
428     // The base rule is that a newly connected tuner always wins, i.e. always gets a tuner
429     // and can use the audio source if requested.
430     // If another client is preempted, it is notified by a callback with RADIO_EVENT_CONTROL
431     // indicating loss of control.
432     // - If the newly connected client requests the audio source (audio == true):
433     //    - if an audio source is available
434     //          no problem
435     //    - if not:
436     //          the oldest client in the list using audio is preempted.
437     // - If the newly connected client does not request the audio source (audio == false):
438     //    - if a tuner is available
439     //          no problem
440     //    - if not:
441     //          The oldest client not using audio is preempted first and if none is found the
442     //          the oldest client using audio is preempted.
443     // Each time a tuner using the audio source is opened or closed, the audio policy manager is
444     // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
445 
446     sp<ModuleClient> oldestTuner;
447     sp<ModuleClient> oldestAudio;
448     size_t allocatedTuners = 0;
449     size_t allocatedAudio = 0;
450     for (size_t i = 0; i < mModuleClients.size(); i++) {
451         if (mModuleClients[i]->getTuner() != NULL) {
452             if (mModuleClients[i]->audio()) {
453                 if (oldestAudio == 0) {
454                     oldestAudio = mModuleClients[i];
455                 }
456                 allocatedAudio++;
457             } else {
458                 if (oldestTuner == 0) {
459                     oldestTuner = mModuleClients[i];
460                 }
461                 allocatedTuners++;
462             }
463         }
464     }
465 
466     const struct radio_tuner *halTuner;
467     sp<ModuleClient> preemtedClient;
468     if (audio) {
469         if (allocatedAudio >= mProperties.num_audio_sources) {
470             ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
471             preemtedClient = oldestAudio;
472         }
473     } else {
474         if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
475             if (allocatedTuners != 0) {
476                 ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
477                 preemtedClient = oldestTuner;
478             } else {
479                 ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
480                 preemtedClient = oldestAudio;
481             }
482         }
483     }
484     if (preemtedClient != 0) {
485         halTuner = preemtedClient->getTuner();
486         preemtedClient->setTuner(NULL);
487         mHwDevice->close_tuner(mHwDevice, halTuner);
488         if (preemtedClient->audio()) {
489             notifyDeviceConnection(false, "");
490         }
491     }
492 
493     ret = mHwDevice->open_tuner(mHwDevice, &halConfig, audio,
494                                 RadioService::callback, moduleClient->callbackThread().get(),
495                                 &halTuner);
496     if (ret == 0) {
497         ALOGV("addClient() setTuner %p", halTuner);
498         moduleClient->setTuner(halTuner);
499         mModuleClients.add(moduleClient);
500         if (audio) {
501             notifyDeviceConnection(true, "");
502         }
503         ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
504     } else {
505         ALOGW("%s open_tuner failed with error %d", __FUNCTION__, ret);
506         moduleClient.clear();
507     }
508 
509     return moduleClient;
510 }
511 
removeClient(const sp<ModuleClient> & moduleClient)512 void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
513     ALOGV("removeClient()");
514     AutoMutex lock(mLock);
515     int ret;
516     ssize_t index = -1;
517 
518     for (size_t i = 0; i < mModuleClients.size(); i++) {
519         if (mModuleClients[i] == moduleClient) {
520             index = i;
521             break;
522         }
523     }
524     if (index == -1) {
525         return;
526     }
527 
528     mModuleClients.removeAt(index);
529     const struct radio_tuner *halTuner = moduleClient->getTuner();
530     if (halTuner == NULL) {
531         return;
532     }
533 
534     mHwDevice->close_tuner(mHwDevice, halTuner);
535     if (moduleClient->audio()) {
536         notifyDeviceConnection(false, "");
537     }
538 
539     mMute = true;
540 
541     if (mModuleClients.isEmpty()) {
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->open_tuner(mHwDevice, &halConfig, youngestClient->audio(),
594                                 RadioService::callback, moduleClient->callbackThread().get(),
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(NULL)
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 
dump(int fd __unused,const Vector<String16> & args __unused)668 status_t RadioService::ModuleClient::dump(int fd __unused,
669                                              const Vector<String16>& args __unused) {
670     String8 result;
671     return NO_ERROR;
672 }
673 
detach()674 void RadioService::ModuleClient::detach() {
675     ALOGV("%s", __FUNCTION__);
676     sp<ModuleClient> strongMe = this;
677     {
678         AutoMutex lock(mLock);
679         if (mClient != 0) {
680             IInterface::asBinder(mClient)->unlinkToDeath(this);
681             mClient.clear();
682         }
683     }
684     sp<Module> module = mModule.promote();
685     if (module == 0) {
686         return;
687     }
688     module->removeClient(this);
689 }
690 
halConfig() const691 radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
692 {
693     AutoMutex lock(mLock);
694     ALOGV("%s locked", __FUNCTION__);
695     return mConfig.band;
696 }
697 
getTuner() const698 const struct radio_tuner *RadioService::ModuleClient::getTuner() const
699 {
700     AutoMutex lock(mLock);
701     ALOGV("%s locked", __FUNCTION__);
702     return mTuner;
703 }
704 
setTuner(const struct radio_tuner * tuner)705 void RadioService::ModuleClient::setTuner(const struct radio_tuner *tuner)
706 {
707     ALOGV("%s %p", __FUNCTION__, this);
708 
709     AutoMutex lock(mLock);
710     mTuner = tuner;
711     ALOGV("%s locked", __FUNCTION__);
712 
713     radio_hal_event_t event;
714     event.type = RADIO_EVENT_CONTROL;
715     event.status = 0;
716     event.on = mTuner != NULL;
717     mCallbackThread->sendEvent(&event);
718     ALOGV("%s DONE", __FUNCTION__);
719 
720 }
721 
setConfiguration(const struct radio_band_config * config)722 status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
723 {
724     AutoMutex lock(mLock);
725     status_t status = NO_ERROR;
726     ALOGV("%s locked", __FUNCTION__);
727 
728     if (mTuner != NULL) {
729         struct radio_hal_band_config halConfig;
730         halConfig = config->band;
731         status = (status_t)mTuner->set_configuration(mTuner, &halConfig);
732         if (status == NO_ERROR) {
733             mConfig = *config;
734         }
735     } else {
736         mConfig = *config;
737         status == INVALID_OPERATION;
738     }
739 
740     return status;
741 }
742 
getConfiguration(struct radio_band_config * config)743 status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
744 {
745     AutoMutex lock(mLock);
746     status_t status = NO_ERROR;
747     ALOGV("%s locked", __FUNCTION__);
748 
749     if (mTuner != NULL) {
750         struct radio_hal_band_config halConfig;
751         status = (status_t)mTuner->get_configuration(mTuner, &halConfig);
752         if (status == NO_ERROR) {
753             mConfig.band = halConfig;
754         }
755     }
756     *config = mConfig;
757 
758     return status;
759 }
760 
setMute(bool mute)761 status_t RadioService::ModuleClient::setMute(bool mute)
762 {
763     sp<Module> module;
764     {
765         Mutex::Autolock _l(mLock);
766         ALOGV("%s locked", __FUNCTION__);
767         if (mTuner == NULL || !mAudio) {
768             return INVALID_OPERATION;
769         }
770         module = mModule.promote();
771         if (module == 0) {
772             return NO_INIT;
773         }
774     }
775     module->setMute(mute);
776     return NO_ERROR;
777 }
778 
getMute(bool * mute)779 status_t RadioService::ModuleClient::getMute(bool *mute)
780 {
781     sp<Module> module;
782     {
783         Mutex::Autolock _l(mLock);
784         ALOGV("%s locked", __FUNCTION__);
785         module = mModule.promote();
786         if (module == 0) {
787             return NO_INIT;
788         }
789     }
790     return module->getMute(mute);
791 }
792 
scan(radio_direction_t direction,bool skipSubChannel)793 status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
794 {
795     AutoMutex lock(mLock);
796     ALOGV("%s locked", __FUNCTION__);
797     status_t status;
798     if (mTuner != NULL) {
799         status = (status_t)mTuner->scan(mTuner, direction, skipSubChannel);
800     } else {
801         status = INVALID_OPERATION;
802     }
803     return status;
804 }
805 
step(radio_direction_t direction,bool skipSubChannel)806 status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
807 {
808     AutoMutex lock(mLock);
809     ALOGV("%s locked", __FUNCTION__);
810     status_t status;
811     if (mTuner != NULL) {
812         status = (status_t)mTuner->step(mTuner, direction, skipSubChannel);
813     } else {
814         status = INVALID_OPERATION;
815     }
816     return status;
817 }
818 
tune(unsigned int channel,unsigned int subChannel)819 status_t RadioService::ModuleClient::tune(unsigned int channel, unsigned int subChannel)
820 {
821     AutoMutex lock(mLock);
822     ALOGV("%s locked", __FUNCTION__);
823     status_t status;
824     if (mTuner != NULL) {
825         status = (status_t)mTuner->tune(mTuner, channel, subChannel);
826     } else {
827         status = INVALID_OPERATION;
828     }
829     return status;
830 }
831 
cancel()832 status_t RadioService::ModuleClient::cancel()
833 {
834     AutoMutex lock(mLock);
835     ALOGV("%s locked", __FUNCTION__);
836     status_t status;
837     if (mTuner != NULL) {
838         status = (status_t)mTuner->cancel(mTuner);
839     } else {
840         status = INVALID_OPERATION;
841     }
842     return status;
843 }
844 
getProgramInformation(struct radio_program_info * info)845 status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
846 {
847     AutoMutex lock(mLock);
848     ALOGV("%s locked", __FUNCTION__);
849     status_t status;
850     if (mTuner != NULL) {
851         status = (status_t)mTuner->get_program_information(mTuner, info);
852     } else {
853         status = INVALID_OPERATION;
854     }
855     return status;
856 }
857 
hasControl(bool * hasControl)858 status_t RadioService::ModuleClient::hasControl(bool *hasControl)
859 {
860     Mutex::Autolock lock(mLock);
861     ALOGV("%s locked", __FUNCTION__);
862     *hasControl = mTuner != NULL;
863     return NO_ERROR;
864 }
865 
onCallbackEvent(const sp<IMemory> & eventMemory)866 void RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory)
867 {
868     if (eventMemory == 0 || eventMemory->pointer() == NULL) {
869         return;
870     }
871 
872     sp<IRadioClient> client;
873     {
874         AutoMutex lock(mLock);
875         ALOGV("%s locked", __FUNCTION__);
876         radio_event_t *event = (radio_event_t *)eventMemory->pointer();
877         switch (event->type) {
878         case RADIO_EVENT_CONFIG:
879             mConfig.band = event->config.band;
880             event->config.region = mConfig.region;
881             break;
882         default:
883             break;
884         }
885 
886         client = mClient;
887     }
888     if (client != 0) {
889         client->onEvent(eventMemory);
890     }
891 }
892 
893 
binderDied(const wp<IBinder> & who __unused)894 void RadioService::ModuleClient::binderDied(
895     const wp<IBinder> &who __unused) {
896     ALOGW("client binder died for client %p", this);
897     detach();
898 }
899 
900 }; // namespace android
901