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