RadioService.cpp revision f2f79cfcdec89052f49b74f9aab48e58daf606c6
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 42namespace android { 43 44static const char kRadioTunerAudioDeviceName[] = "Radio tuner source"; 45 46RadioService::RadioService() 47 : BnRadioService(), mNextUniqueId(1) 48{ 49 ALOGI("%s", __FUNCTION__); 50} 51 52void 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 95RadioService::~RadioService() 96{ 97 for (size_t i = 0; i < mModules.size(); i++) { 98 radio_hw_device_close(mModules.valueAt(i)->hwDevice()); 99 } 100} 101 102status_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 119status_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 155static const int kDumpLockRetries = 50; 156static const int kDumpLockSleep = 60000; 157 158static 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 171status_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 189status_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 196void 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 */ 206void 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 255RadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient) 256 : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService")) 257{ 258} 259 260RadioService::CallbackThread::~CallbackThread() 261{ 262 mEventQueue.clear(); 263} 264 265void RadioService::CallbackThread::onFirstRef() 266{ 267 run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO); 268} 269 270bool 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 297void RadioService::CallbackThread::exit() 298{ 299 Mutex::Autolock _l(mCallbackLock); 300 requestExit(); 301 mCallbackCond.broadcast(); 302} 303 304sp<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 370void 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 387RadioService::Module::Module(radio_hw_device* hwDevice, radio_properties properties) 388 : mHwDevice(hwDevice), mProperties(properties), mMute(true) 389{ 390} 391 392RadioService::Module::~Module() { 393 mModuleClients.clear(); 394} 395 396status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) { 397 String8 result; 398 return NO_ERROR; 399} 400 401sp<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 512void 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 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(NULL) 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 668status_t RadioService::ModuleClient::dump(int fd __unused, 669 const Vector<String16>& args __unused) { 670 String8 result; 671 return NO_ERROR; 672} 673 674void 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 691radio_hal_band_config_t RadioService::ModuleClient::halConfig() const 692{ 693 AutoMutex lock(mLock); 694 ALOGV("%s locked", __FUNCTION__); 695 return mConfig.band; 696} 697 698const struct radio_tuner *RadioService::ModuleClient::getTuner() const 699{ 700 AutoMutex lock(mLock); 701 ALOGV("%s locked", __FUNCTION__); 702 return mTuner; 703} 704 705void 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 722status_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 743status_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 761status_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 779status_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 793status_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 806status_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 819status_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 832status_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 845status_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 858status_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 866void 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 894void 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