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 43namespace android { 44 45static const char kRadioTunerAudioDeviceName[] = "Radio tuner source"; 46 47static const String16 RADIO_PERMISSION("android.permission.ACCESS_FM_RADIO"); 48 49RadioService::RadioService() 50 : BnRadioService(), mNextUniqueId(1) 51{ 52 ALOGI("%s", __FUNCTION__); 53} 54 55void 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 83RadioService::~RadioService() 84{ 85} 86 87status_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 107status_t RadioService::attach(radio_handle_t handle, 108 const sp<IRadioClient>& client, 109 const struct radio_band_config *config, 110 bool withAudio, 111 sp<IRadio>& radio) 112{ 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 146static const int kDumpLockRetries = 50; 147static const int kDumpLockSleep = 60000; 148 149static bool tryLock(Mutex& mutex) 150{ 151 bool locked = false; 152 for (int i = 0; i < kDumpLockRetries; ++i) { 153 if (mutex.tryLock() == NO_ERROR) { 154 locked = true; 155 break; 156 } 157 usleep(kDumpLockSleep); 158 } 159 return locked; 160} 161 162status_t RadioService::dump(int fd, const Vector<String16>& args __unused) { 163 String8 result; 164 if (checkCallingPermission(String16("android.permission.DUMP")) == false) { 165 result.appendFormat("Permission Denial: can't dump RadioService"); 166 write(fd, result.string(), result.size()); 167 } else { 168 bool locked = tryLock(mServiceLock); 169 // failed to lock - RadioService is probably deadlocked 170 if (!locked) { 171 result.append("RadioService may be deadlocked\n"); 172 write(fd, result.string(), result.size()); 173 } 174 175 if (locked) mServiceLock.unlock(); 176 } 177 return NO_ERROR; 178} 179 180status_t RadioService::onTransact( 181 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { 182 return BnRadioService::onTransact(code, data, reply, flags); 183} 184 185 186/* static */ 187void RadioService::convertProperties(radio_properties_t *properties, 188 const radio_hal_properties_t *halProperties) 189{ 190 memset(properties, 0, sizeof(struct radio_properties)); 191 properties->class_id = halProperties->class_id; 192 strlcpy(properties->implementor, halProperties->implementor, 193 RADIO_STRING_LEN_MAX); 194 strlcpy(properties->product, halProperties->product, 195 RADIO_STRING_LEN_MAX); 196 strlcpy(properties->version, halProperties->version, 197 RADIO_STRING_LEN_MAX); 198 strlcpy(properties->serial, halProperties->serial, 199 RADIO_STRING_LEN_MAX); 200 properties->num_tuners = halProperties->num_tuners; 201 properties->num_audio_sources = halProperties->num_audio_sources; 202 properties->supports_capture = halProperties->supports_capture; 203 204 for (size_t i = 0; i < ARRAY_SIZE(sKnownRegionConfigs); i++) { 205 const radio_hal_band_config_t *band = &sKnownRegionConfigs[i].band; 206 size_t j; 207 for (j = 0; j < halProperties->num_bands; j++) { 208 const radio_hal_band_config_t *halBand = &halProperties->bands[j]; 209 size_t k; 210 if (band->type != halBand->type) continue; 211 if (band->lower_limit < halBand->lower_limit) continue; 212 if (band->upper_limit > halBand->upper_limit) continue; 213 for (k = 0; k < halBand->num_spacings; k++) { 214 if (band->spacings[0] == halBand->spacings[k]) break; 215 } 216 if (k == halBand->num_spacings) continue; 217 if (band->type == RADIO_BAND_AM) break; 218 if ((band->fm.deemphasis & halBand->fm.deemphasis) == 0) continue; 219 if (halBand->fm.rds == 0) break; 220 if ((band->fm.rds & halBand->fm.rds) != 0) break; 221 } 222 if (j == halProperties->num_bands) continue; 223 224 ALOGI("convertProperties() Adding band type %d region %d", 225 sKnownRegionConfigs[i].band.type , sKnownRegionConfigs[i].region); 226 227 memcpy(&properties->bands[properties->num_bands++], 228 &sKnownRegionConfigs[i], 229 sizeof(radio_band_config_t)); 230 } 231} 232 233#undef LOG_TAG 234#define LOG_TAG "RadioService::CallbackThread" 235 236RadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient) 237 : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService")) 238{ 239} 240 241RadioService::CallbackThread::~CallbackThread() 242{ 243 mEventQueue.clear(); 244} 245 246void RadioService::CallbackThread::onFirstRef() 247{ 248 run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO); 249} 250 251bool RadioService::CallbackThread::threadLoop() 252{ 253 while (!exitPending()) { 254 sp<IMemory> eventMemory; 255 sp<ModuleClient> moduleClient; 256 { 257 Mutex::Autolock _l(mCallbackLock); 258 while (mEventQueue.isEmpty() && !exitPending()) { 259 ALOGV("CallbackThread::threadLoop() sleep"); 260 mCallbackCond.wait(mCallbackLock); 261 ALOGV("CallbackThread::threadLoop() wake up"); 262 } 263 if (exitPending()) { 264 break; 265 } 266 eventMemory = mEventQueue[0]; 267 mEventQueue.removeAt(0); 268 moduleClient = mModuleClient.promote(); 269 } 270 if (moduleClient != 0) { 271 moduleClient->onCallbackEvent(eventMemory); 272 eventMemory.clear(); 273 } 274 } 275 return false; 276} 277 278void RadioService::CallbackThread::exit() 279{ 280 Mutex::Autolock _l(mCallbackLock); 281 requestExit(); 282 mCallbackCond.broadcast(); 283} 284 285sp<IMemory> RadioService::CallbackThread::prepareEvent(radio_hal_event_t *halEvent) 286{ 287 sp<IMemory> eventMemory; 288 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 356void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event) 357 { 358 sp<IMemory> eventMemory = prepareEvent(event); 359 if (eventMemory == 0) { 360 return; 361 } 362 363 AutoMutex lock(mCallbackLock); 364 mEventQueue.add(eventMemory); 365 mCallbackCond.signal(); 366 ALOGV("%s DONE", __FUNCTION__); 367} 368 369 370#undef LOG_TAG 371#define LOG_TAG "RadioService::Module" 372 373RadioService::Module::Module(sp<RadioInterface> hwDevice, radio_properties properties) 374 : mHwDevice(hwDevice), mProperties(properties), mMute(true) 375{ 376} 377 378RadioService::Module::~Module() { 379 mHwDevice.clear(); 380 mModuleClients.clear(); 381} 382 383status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) { 384 String8 result; 385 return NO_ERROR; 386} 387 388sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client, 389 const struct radio_band_config *config, 390 bool audio) 391{ 392 ALOGV("addClient() %p config %p product %s", this, config, mProperties.product); 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 505void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) { 506 ALOGV("removeClient()"); 507 AutoMutex lock(mLock); 508 int ret; 509 ssize_t index = -1; 510 511 for (size_t i = 0; i < mModuleClients.size(); i++) { 512 if (mModuleClients[i] == moduleClient) { 513 index = i; 514 break; 515 } 516 } 517 if (index == -1) { 518 return; 519 } 520 521 mModuleClients.removeAt(index); 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 605status_t RadioService::Module::setMute(bool mute) 606{ 607 Mutex::Autolock _l(mLock); 608 if (mute != mMute) { 609 mMute = mute; 610 //TODO notifify audio policy manager of media activity on radio audio device 611 } 612 return NO_ERROR; 613} 614 615status_t RadioService::Module::getMute(bool *mute) 616{ 617 Mutex::Autolock _l(mLock); 618 *mute = mMute; 619 return NO_ERROR; 620} 621 622 623const struct radio_band_config *RadioService::Module::getDefaultConfig() const 624{ 625 if (mProperties.num_bands == 0) { 626 return NULL; 627 } 628 return &mProperties.bands[0]; 629} 630 631void 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 644RadioService::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 652void RadioService::ModuleClient::onFirstRef() 653{ 654 mCallbackThread = new CallbackThread(this); 655 IInterface::asBinder(mClient)->linkToDeath(this); 656} 657 658RadioService::ModuleClient::~ModuleClient() { 659 if (mClient != 0) { 660 IInterface::asBinder(mClient)->unlinkToDeath(this); 661 mClient.clear(); 662 } 663 if (mCallbackThread != 0) { 664 mCallbackThread->exit(); 665 } 666} 667 668void RadioService::ModuleClient::onEvent(radio_hal_event_t *halEvent) 669{ 670 mCallbackThread->sendEvent(halEvent); 671} 672 673status_t RadioService::ModuleClient::dump(int fd __unused, 674 const Vector<String16>& args __unused) { 675 String8 result; 676 return NO_ERROR; 677} 678 679void RadioService::ModuleClient::detach() { 680 ALOGV("%s", __FUNCTION__); 681 sp<ModuleClient> strongMe = this; 682 { 683 AutoMutex lock(mLock); 684 if (mClient != 0) { 685 IInterface::asBinder(mClient)->unlinkToDeath(this); 686 mClient.clear(); 687 } 688 } 689 sp<Module> module = mModule.promote(); 690 if (module == 0) { 691 return; 692 } 693 module->removeClient(this); 694} 695 696radio_hal_band_config_t RadioService::ModuleClient::halConfig() const 697{ 698 AutoMutex lock(mLock); 699 ALOGV("%s locked", __FUNCTION__); 700 return mConfig.band; 701} 702 703sp<TunerInterface>& RadioService::ModuleClient::getTuner() 704{ 705 AutoMutex lock(mLock); 706 ALOGV("%s locked", __FUNCTION__); 707 return mTuner; 708} 709 710void 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 727status_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 751status_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 772status_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 793status_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 810status_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 826status_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 842status_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 858status_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 874status_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 891status_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 902void RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory) 903{ 904 if (eventMemory == 0 || eventMemory->pointer() == NULL) { 905 return; 906 } 907 908 sp<IRadioClient> client; 909 { 910 AutoMutex lock(mLock); 911 ALOGV("%s locked", __FUNCTION__); 912 radio_event_t *event = (radio_event_t *)eventMemory->pointer(); 913 switch (event->type) { 914 case RADIO_EVENT_CONFIG: 915 mConfig.band = event->config.band; 916 event->config.region = mConfig.region; 917 break; 918 default: 919 break; 920 } 921 922 client = mClient; 923 } 924 if (client != 0) { 925 client->onEvent(eventMemory); 926 } 927} 928 929 930void RadioService::ModuleClient::binderDied( 931 const wp<IBinder> &who __unused) { 932 ALOGW("client binder died for client %p", this); 933 detach(); 934} 935 936}; // namespace android 937