AudioPolicyService.cpp revision de80105c3f2db0eabd47640c49387ea3b44d4782
1/* 2 * Copyright (C) 2009 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 "AudioPolicyService" 18//#define LOG_NDEBUG 0 19 20#include "Configuration.h" 21#undef __STRICT_ANSI__ 22#define __STDINT_LIMITS 23#define __STDC_LIMIT_MACROS 24#include <stdint.h> 25 26#include <sys/time.h> 27#include <binder/IServiceManager.h> 28#include <utils/Log.h> 29#include <cutils/properties.h> 30#include <binder/IPCThreadState.h> 31#include <utils/String16.h> 32#include <utils/threads.h> 33#include "AudioPolicyService.h" 34#include "ServiceUtilities.h" 35#include <hardware_legacy/power.h> 36#include <media/AudioEffect.h> 37#include <media/EffectsFactoryApi.h> 38#include <media/AudioParameter.h> 39 40#include <hardware/hardware.h> 41#include <system/audio.h> 42#include <system/audio_policy.h> 43#include <hardware/audio_policy.h> 44 45namespace android { 46 47static const char kDeadlockedString[] = "AudioPolicyService may be deadlocked\n"; 48static const char kCmdDeadlockedString[] = "AudioPolicyService command thread may be deadlocked\n"; 49 50static const int kDumpLockRetries = 50; 51static const int kDumpLockSleepUs = 20000; 52 53static const nsecs_t kAudioCommandTimeoutNs = seconds(3); // 3 seconds 54 55namespace { 56 extern struct audio_policy_service_ops aps_ops; 57}; 58 59// ---------------------------------------------------------------------------- 60 61AudioPolicyService::AudioPolicyService() 62 : BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL), 63 mAudioPolicyManager(NULL), mAudioPolicyClient(NULL), mPhoneState(AUDIO_MODE_INVALID) 64{ 65} 66 67void AudioPolicyService::onFirstRef() 68{ 69 char value[PROPERTY_VALUE_MAX]; 70 const struct hw_module_t *module; 71 int forced_val; 72 int rc; 73 74 { 75 Mutex::Autolock _l(mLock); 76 77 // start tone playback thread 78 mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this); 79 // start audio commands thread 80 mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this); 81 // start output activity command thread 82 mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this); 83 84#ifdef USE_LEGACY_AUDIO_POLICY 85 ALOGI("AudioPolicyService CSTOR in legacy mode"); 86 87 /* instantiate the audio policy manager */ 88 rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module); 89 if (rc) { 90 return; 91 } 92 rc = audio_policy_dev_open(module, &mpAudioPolicyDev); 93 ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc)); 94 if (rc) { 95 return; 96 } 97 98 rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this, 99 &mpAudioPolicy); 100 ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc)); 101 if (rc) { 102 return; 103 } 104 105 rc = mpAudioPolicy->init_check(mpAudioPolicy); 106 ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc)); 107 if (rc) { 108 return; 109 } 110 ALOGI("Loaded audio policy from %s (%s)", module->name, module->id); 111#else 112 ALOGI("AudioPolicyService CSTOR in new mode"); 113 114 mAudioPolicyClient = new AudioPolicyClient(this); 115 mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient); 116#endif 117 } 118 // load audio processing modules 119 sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects(); 120 { 121 Mutex::Autolock _l(mLock); 122 mAudioPolicyEffects = audioPolicyEffects; 123 } 124} 125 126AudioPolicyService::~AudioPolicyService() 127{ 128 mTonePlaybackThread->exit(); 129 mAudioCommandThread->exit(); 130 mOutputCommandThread->exit(); 131 132#ifdef USE_LEGACY_AUDIO_POLICY 133 if (mpAudioPolicy != NULL && mpAudioPolicyDev != NULL) { 134 mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy); 135 } 136 if (mpAudioPolicyDev != NULL) { 137 audio_policy_dev_close(mpAudioPolicyDev); 138 } 139#else 140 destroyAudioPolicyManager(mAudioPolicyManager); 141 delete mAudioPolicyClient; 142#endif 143 144 mNotificationClients.clear(); 145 mAudioPolicyEffects.clear(); 146} 147 148// A notification client is always registered by AudioSystem when the client process 149// connects to AudioPolicyService. 150void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client) 151{ 152 153 Mutex::Autolock _l(mNotificationClientsLock); 154 155 uid_t uid = IPCThreadState::self()->getCallingUid(); 156 if (mNotificationClients.indexOfKey(uid) < 0) { 157 sp<NotificationClient> notificationClient = new NotificationClient(this, 158 client, 159 uid); 160 ALOGV("registerClient() client %p, uid %d", client.get(), uid); 161 162 mNotificationClients.add(uid, notificationClient); 163 164 sp<IBinder> binder = IInterface::asBinder(client); 165 binder->linkToDeath(notificationClient); 166 } 167} 168 169// removeNotificationClient() is called when the client process dies. 170void AudioPolicyService::removeNotificationClient(uid_t uid) 171{ 172 { 173 Mutex::Autolock _l(mNotificationClientsLock); 174 mNotificationClients.removeItem(uid); 175 } 176#ifndef USE_LEGACY_AUDIO_POLICY 177 { 178 Mutex::Autolock _l(mLock); 179 if (mAudioPolicyManager) { 180 mAudioPolicyManager->clearAudioPatches(uid); 181 } 182 } 183#endif 184} 185 186void AudioPolicyService::onAudioPortListUpdate() 187{ 188 mOutputCommandThread->updateAudioPortListCommand(); 189} 190 191void AudioPolicyService::doOnAudioPortListUpdate() 192{ 193 Mutex::Autolock _l(mNotificationClientsLock); 194 for (size_t i = 0; i < mNotificationClients.size(); i++) { 195 mNotificationClients.valueAt(i)->onAudioPortListUpdate(); 196 } 197} 198 199void AudioPolicyService::onAudioPatchListUpdate() 200{ 201 mOutputCommandThread->updateAudioPatchListCommand(); 202} 203 204status_t AudioPolicyService::clientCreateAudioPatch(const struct audio_patch *patch, 205 audio_patch_handle_t *handle, 206 int delayMs) 207{ 208 return mAudioCommandThread->createAudioPatchCommand(patch, handle, delayMs); 209} 210 211status_t AudioPolicyService::clientReleaseAudioPatch(audio_patch_handle_t handle, 212 int delayMs) 213{ 214 return mAudioCommandThread->releaseAudioPatchCommand(handle, delayMs); 215} 216 217void AudioPolicyService::doOnAudioPatchListUpdate() 218{ 219 Mutex::Autolock _l(mNotificationClientsLock); 220 for (size_t i = 0; i < mNotificationClients.size(); i++) { 221 mNotificationClients.valueAt(i)->onAudioPatchListUpdate(); 222 } 223} 224 225void AudioPolicyService::onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) 226{ 227 ALOGV("AudioPolicyService::onDynamicPolicyMixStateUpdate(%s, %d)", 228 regId.string(), state); 229 mOutputCommandThread->dynamicPolicyMixStateUpdateCommand(regId, state); 230} 231 232void AudioPolicyService::doOnDynamicPolicyMixStateUpdate(String8 regId, int32_t state) 233{ 234 Mutex::Autolock _l(mNotificationClientsLock); 235 for (size_t i = 0; i < mNotificationClients.size(); i++) { 236 mNotificationClients.valueAt(i)->onDynamicPolicyMixStateUpdate(regId, state); 237 } 238} 239 240status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_config *config, 241 int delayMs) 242{ 243 return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs); 244} 245 246AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service, 247 const sp<IAudioPolicyServiceClient>& client, 248 uid_t uid) 249 : mService(service), mUid(uid), mAudioPolicyServiceClient(client) 250{ 251} 252 253AudioPolicyService::NotificationClient::~NotificationClient() 254{ 255} 256 257void AudioPolicyService::NotificationClient::binderDied(const wp<IBinder>& who __unused) 258{ 259 sp<NotificationClient> keep(this); 260 sp<AudioPolicyService> service = mService.promote(); 261 if (service != 0) { 262 service->removeNotificationClient(mUid); 263 } 264} 265 266void AudioPolicyService::NotificationClient::onAudioPortListUpdate() 267{ 268 if (mAudioPolicyServiceClient != 0) { 269 mAudioPolicyServiceClient->onAudioPortListUpdate(); 270 } 271} 272 273void AudioPolicyService::NotificationClient::onAudioPatchListUpdate() 274{ 275 if (mAudioPolicyServiceClient != 0) { 276 mAudioPolicyServiceClient->onAudioPatchListUpdate(); 277 } 278} 279 280void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate( 281 String8 regId, int32_t state) 282{ 283 if (mAudioPolicyServiceClient != 0) { 284 mAudioPolicyServiceClient->onDynamicPolicyMixStateUpdate(regId, state); 285 } 286} 287 288void AudioPolicyService::binderDied(const wp<IBinder>& who) { 289 ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(), 290 IPCThreadState::self()->getCallingPid()); 291} 292 293static bool tryLock(Mutex& mutex) 294{ 295 bool locked = false; 296 for (int i = 0; i < kDumpLockRetries; ++i) { 297 if (mutex.tryLock() == NO_ERROR) { 298 locked = true; 299 break; 300 } 301 usleep(kDumpLockSleepUs); 302 } 303 return locked; 304} 305 306status_t AudioPolicyService::dumpInternals(int fd) 307{ 308 const size_t SIZE = 256; 309 char buffer[SIZE]; 310 String8 result; 311 312#ifdef USE_LEGACY_AUDIO_POLICY 313 snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpAudioPolicy); 314#else 315 snprintf(buffer, SIZE, "AudioPolicyManager: %p\n", mAudioPolicyManager); 316#endif 317 result.append(buffer); 318 snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get()); 319 result.append(buffer); 320 snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get()); 321 result.append(buffer); 322 323 write(fd, result.string(), result.size()); 324 return NO_ERROR; 325} 326 327status_t AudioPolicyService::dump(int fd, const Vector<String16>& args __unused) 328{ 329 if (!dumpAllowed()) { 330 dumpPermissionDenial(fd); 331 } else { 332 bool locked = tryLock(mLock); 333 if (!locked) { 334 String8 result(kDeadlockedString); 335 write(fd, result.string(), result.size()); 336 } 337 338 dumpInternals(fd); 339 if (mAudioCommandThread != 0) { 340 mAudioCommandThread->dump(fd); 341 } 342 if (mTonePlaybackThread != 0) { 343 mTonePlaybackThread->dump(fd); 344 } 345 346#ifdef USE_LEGACY_AUDIO_POLICY 347 if (mpAudioPolicy) { 348 mpAudioPolicy->dump(mpAudioPolicy, fd); 349 } 350#else 351 if (mAudioPolicyManager) { 352 mAudioPolicyManager->dump(fd); 353 } 354#endif 355 356 if (locked) mLock.unlock(); 357 } 358 return NO_ERROR; 359} 360 361status_t AudioPolicyService::dumpPermissionDenial(int fd) 362{ 363 const size_t SIZE = 256; 364 char buffer[SIZE]; 365 String8 result; 366 snprintf(buffer, SIZE, "Permission Denial: " 367 "can't dump AudioPolicyService from pid=%d, uid=%d\n", 368 IPCThreadState::self()->getCallingPid(), 369 IPCThreadState::self()->getCallingUid()); 370 result.append(buffer); 371 write(fd, result.string(), result.size()); 372 return NO_ERROR; 373} 374 375status_t AudioPolicyService::onTransact( 376 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 377{ 378 return BnAudioPolicyService::onTransact(code, data, reply, flags); 379} 380 381 382// ----------- AudioPolicyService::AudioCommandThread implementation ---------- 383 384AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name, 385 const wp<AudioPolicyService>& service) 386 : Thread(false), mName(name), mService(service) 387{ 388 mpToneGenerator = NULL; 389} 390 391 392AudioPolicyService::AudioCommandThread::~AudioCommandThread() 393{ 394 if (!mAudioCommands.isEmpty()) { 395 release_wake_lock(mName.string()); 396 } 397 mAudioCommands.clear(); 398 delete mpToneGenerator; 399} 400 401void AudioPolicyService::AudioCommandThread::onFirstRef() 402{ 403 run(mName.string(), ANDROID_PRIORITY_AUDIO); 404} 405 406bool AudioPolicyService::AudioCommandThread::threadLoop() 407{ 408 nsecs_t waitTime = INT64_MAX; 409 410 mLock.lock(); 411 while (!exitPending()) 412 { 413 sp<AudioPolicyService> svc; 414 while (!mAudioCommands.isEmpty() && !exitPending()) { 415 nsecs_t curTime = systemTime(); 416 // commands are sorted by increasing time stamp: execute them from index 0 and up 417 if (mAudioCommands[0]->mTime <= curTime) { 418 sp<AudioCommand> command = mAudioCommands[0]; 419 mAudioCommands.removeAt(0); 420 mLastCommand = command; 421 422 switch (command->mCommand) { 423 case START_TONE: { 424 mLock.unlock(); 425 ToneData *data = (ToneData *)command->mParam.get(); 426 ALOGV("AudioCommandThread() processing start tone %d on stream %d", 427 data->mType, data->mStream); 428 delete mpToneGenerator; 429 mpToneGenerator = new ToneGenerator(data->mStream, 1.0); 430 mpToneGenerator->startTone(data->mType); 431 mLock.lock(); 432 }break; 433 case STOP_TONE: { 434 mLock.unlock(); 435 ALOGV("AudioCommandThread() processing stop tone"); 436 if (mpToneGenerator != NULL) { 437 mpToneGenerator->stopTone(); 438 delete mpToneGenerator; 439 mpToneGenerator = NULL; 440 } 441 mLock.lock(); 442 }break; 443 case SET_VOLUME: { 444 VolumeData *data = (VolumeData *)command->mParam.get(); 445 ALOGV("AudioCommandThread() processing set volume stream %d, \ 446 volume %f, output %d", data->mStream, data->mVolume, data->mIO); 447 command->mStatus = AudioSystem::setStreamVolume(data->mStream, 448 data->mVolume, 449 data->mIO); 450 }break; 451 case SET_PARAMETERS: { 452 ParametersData *data = (ParametersData *)command->mParam.get(); 453 ALOGV("AudioCommandThread() processing set parameters string %s, io %d", 454 data->mKeyValuePairs.string(), data->mIO); 455 command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs); 456 }break; 457 case SET_VOICE_VOLUME: { 458 VoiceVolumeData *data = (VoiceVolumeData *)command->mParam.get(); 459 ALOGV("AudioCommandThread() processing set voice volume volume %f", 460 data->mVolume); 461 command->mStatus = AudioSystem::setVoiceVolume(data->mVolume); 462 }break; 463 case STOP_OUTPUT: { 464 StopOutputData *data = (StopOutputData *)command->mParam.get(); 465 ALOGV("AudioCommandThread() processing stop output %d", 466 data->mIO); 467 svc = mService.promote(); 468 if (svc == 0) { 469 break; 470 } 471 mLock.unlock(); 472 svc->doStopOutput(data->mIO, data->mStream, data->mSession); 473 mLock.lock(); 474 }break; 475 case RELEASE_OUTPUT: { 476 ReleaseOutputData *data = (ReleaseOutputData *)command->mParam.get(); 477 ALOGV("AudioCommandThread() processing release output %d", 478 data->mIO); 479 svc = mService.promote(); 480 if (svc == 0) { 481 break; 482 } 483 mLock.unlock(); 484 svc->doReleaseOutput(data->mIO, data->mStream, data->mSession); 485 mLock.lock(); 486 }break; 487 case CREATE_AUDIO_PATCH: { 488 CreateAudioPatchData *data = (CreateAudioPatchData *)command->mParam.get(); 489 ALOGV("AudioCommandThread() processing create audio patch"); 490 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 491 if (af == 0) { 492 command->mStatus = PERMISSION_DENIED; 493 } else { 494 command->mStatus = af->createAudioPatch(&data->mPatch, &data->mHandle); 495 } 496 } break; 497 case RELEASE_AUDIO_PATCH: { 498 ReleaseAudioPatchData *data = (ReleaseAudioPatchData *)command->mParam.get(); 499 ALOGV("AudioCommandThread() processing release audio patch"); 500 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 501 if (af == 0) { 502 command->mStatus = PERMISSION_DENIED; 503 } else { 504 command->mStatus = af->releaseAudioPatch(data->mHandle); 505 } 506 } break; 507 case UPDATE_AUDIOPORT_LIST: { 508 ALOGV("AudioCommandThread() processing update audio port list"); 509 svc = mService.promote(); 510 if (svc == 0) { 511 break; 512 } 513 mLock.unlock(); 514 svc->doOnAudioPortListUpdate(); 515 mLock.lock(); 516 }break; 517 case UPDATE_AUDIOPATCH_LIST: { 518 ALOGV("AudioCommandThread() processing update audio patch list"); 519 svc = mService.promote(); 520 if (svc == 0) { 521 break; 522 } 523 mLock.unlock(); 524 svc->doOnAudioPatchListUpdate(); 525 mLock.lock(); 526 }break; 527 case SET_AUDIOPORT_CONFIG: { 528 SetAudioPortConfigData *data = (SetAudioPortConfigData *)command->mParam.get(); 529 ALOGV("AudioCommandThread() processing set port config"); 530 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 531 if (af == 0) { 532 command->mStatus = PERMISSION_DENIED; 533 } else { 534 command->mStatus = af->setAudioPortConfig(&data->mConfig); 535 } 536 } break; 537 case DYN_POLICY_MIX_STATE_UPDATE: { 538 DynPolicyMixStateUpdateData *data = 539 (DynPolicyMixStateUpdateData *)command->mParam.get(); 540 //###ALOGV("AudioCommandThread() processing dyn policy mix state update"); 541 ALOGV("AudioCommandThread() processing dyn policy mix state update %s %d", 542 data->mRegId.string(), data->mState); 543 svc = mService.promote(); 544 if (svc == 0) { 545 break; 546 } 547 mLock.unlock(); 548 svc->doOnDynamicPolicyMixStateUpdate(data->mRegId, data->mState); 549 mLock.lock(); 550 } break; 551 default: 552 ALOGW("AudioCommandThread() unknown command %d", command->mCommand); 553 } 554 { 555 Mutex::Autolock _l(command->mLock); 556 if (command->mWaitStatus) { 557 command->mWaitStatus = false; 558 command->mCond.signal(); 559 } 560 } 561 waitTime = INT64_MAX; 562 } else { 563 waitTime = mAudioCommands[0]->mTime - curTime; 564 break; 565 } 566 } 567 // release mLock before releasing strong reference on the service as 568 // AudioPolicyService destructor calls AudioCommandThread::exit() which acquires mLock. 569 mLock.unlock(); 570 svc.clear(); 571 mLock.lock(); 572 if (!exitPending() && (mAudioCommands.isEmpty() || waitTime != INT64_MAX)) { 573 // release delayed commands wake lock 574 release_wake_lock(mName.string()); 575 ALOGV("AudioCommandThread() going to sleep"); 576 mWaitWorkCV.waitRelative(mLock, waitTime); 577 ALOGV("AudioCommandThread() waking up"); 578 } 579 } 580 // release delayed commands wake lock before quitting 581 if (!mAudioCommands.isEmpty()) { 582 release_wake_lock(mName.string()); 583 } 584 mLock.unlock(); 585 return false; 586} 587 588status_t AudioPolicyService::AudioCommandThread::dump(int fd) 589{ 590 const size_t SIZE = 256; 591 char buffer[SIZE]; 592 String8 result; 593 594 snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this); 595 result.append(buffer); 596 write(fd, result.string(), result.size()); 597 598 bool locked = tryLock(mLock); 599 if (!locked) { 600 String8 result2(kCmdDeadlockedString); 601 write(fd, result2.string(), result2.size()); 602 } 603 604 snprintf(buffer, SIZE, "- Commands:\n"); 605 result = String8(buffer); 606 result.append(" Command Time Wait pParam\n"); 607 for (size_t i = 0; i < mAudioCommands.size(); i++) { 608 mAudioCommands[i]->dump(buffer, SIZE); 609 result.append(buffer); 610 } 611 result.append(" Last Command\n"); 612 if (mLastCommand != 0) { 613 mLastCommand->dump(buffer, SIZE); 614 result.append(buffer); 615 } else { 616 result.append(" none\n"); 617 } 618 619 write(fd, result.string(), result.size()); 620 621 if (locked) mLock.unlock(); 622 623 return NO_ERROR; 624} 625 626void AudioPolicyService::AudioCommandThread::startToneCommand(ToneGenerator::tone_type type, 627 audio_stream_type_t stream) 628{ 629 sp<AudioCommand> command = new AudioCommand(); 630 command->mCommand = START_TONE; 631 sp<ToneData> data = new ToneData(); 632 data->mType = type; 633 data->mStream = stream; 634 command->mParam = data; 635 ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream); 636 sendCommand(command); 637} 638 639void AudioPolicyService::AudioCommandThread::stopToneCommand() 640{ 641 sp<AudioCommand> command = new AudioCommand(); 642 command->mCommand = STOP_TONE; 643 ALOGV("AudioCommandThread() adding tone stop"); 644 sendCommand(command); 645} 646 647status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream, 648 float volume, 649 audio_io_handle_t output, 650 int delayMs) 651{ 652 sp<AudioCommand> command = new AudioCommand(); 653 command->mCommand = SET_VOLUME; 654 sp<VolumeData> data = new VolumeData(); 655 data->mStream = stream; 656 data->mVolume = volume; 657 data->mIO = output; 658 command->mParam = data; 659 command->mWaitStatus = true; 660 ALOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", 661 stream, volume, output); 662 return sendCommand(command, delayMs); 663} 664 665status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_handle_t ioHandle, 666 const char *keyValuePairs, 667 int delayMs) 668{ 669 sp<AudioCommand> command = new AudioCommand(); 670 command->mCommand = SET_PARAMETERS; 671 sp<ParametersData> data = new ParametersData(); 672 data->mIO = ioHandle; 673 data->mKeyValuePairs = String8(keyValuePairs); 674 command->mParam = data; 675 command->mWaitStatus = true; 676 ALOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", 677 keyValuePairs, ioHandle, delayMs); 678 return sendCommand(command, delayMs); 679} 680 681status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs) 682{ 683 sp<AudioCommand> command = new AudioCommand(); 684 command->mCommand = SET_VOICE_VOLUME; 685 sp<VoiceVolumeData> data = new VoiceVolumeData(); 686 data->mVolume = volume; 687 command->mParam = data; 688 command->mWaitStatus = true; 689 ALOGV("AudioCommandThread() adding set voice volume volume %f", volume); 690 return sendCommand(command, delayMs); 691} 692 693void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t output, 694 audio_stream_type_t stream, 695 audio_session_t session) 696{ 697 sp<AudioCommand> command = new AudioCommand(); 698 command->mCommand = STOP_OUTPUT; 699 sp<StopOutputData> data = new StopOutputData(); 700 data->mIO = output; 701 data->mStream = stream; 702 data->mSession = session; 703 command->mParam = data; 704 ALOGV("AudioCommandThread() adding stop output %d", output); 705 sendCommand(command); 706} 707 708void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output, 709 audio_stream_type_t stream, 710 audio_session_t session) 711{ 712 sp<AudioCommand> command = new AudioCommand(); 713 command->mCommand = RELEASE_OUTPUT; 714 sp<ReleaseOutputData> data = new ReleaseOutputData(); 715 data->mIO = output; 716 data->mStream = stream; 717 data->mSession = session; 718 command->mParam = data; 719 ALOGV("AudioCommandThread() adding release output %d", output); 720 sendCommand(command); 721} 722 723status_t AudioPolicyService::AudioCommandThread::createAudioPatchCommand( 724 const struct audio_patch *patch, 725 audio_patch_handle_t *handle, 726 int delayMs) 727{ 728 status_t status = NO_ERROR; 729 730 sp<AudioCommand> command = new AudioCommand(); 731 command->mCommand = CREATE_AUDIO_PATCH; 732 CreateAudioPatchData *data = new CreateAudioPatchData(); 733 data->mPatch = *patch; 734 data->mHandle = *handle; 735 command->mParam = data; 736 command->mWaitStatus = true; 737 ALOGV("AudioCommandThread() adding create patch delay %d", delayMs); 738 status = sendCommand(command, delayMs); 739 if (status == NO_ERROR) { 740 *handle = data->mHandle; 741 } 742 return status; 743} 744 745status_t AudioPolicyService::AudioCommandThread::releaseAudioPatchCommand(audio_patch_handle_t handle, 746 int delayMs) 747{ 748 sp<AudioCommand> command = new AudioCommand(); 749 command->mCommand = RELEASE_AUDIO_PATCH; 750 ReleaseAudioPatchData *data = new ReleaseAudioPatchData(); 751 data->mHandle = handle; 752 command->mParam = data; 753 command->mWaitStatus = true; 754 ALOGV("AudioCommandThread() adding release patch delay %d", delayMs); 755 return sendCommand(command, delayMs); 756} 757 758void AudioPolicyService::AudioCommandThread::updateAudioPortListCommand() 759{ 760 sp<AudioCommand> command = new AudioCommand(); 761 command->mCommand = UPDATE_AUDIOPORT_LIST; 762 ALOGV("AudioCommandThread() adding update audio port list"); 763 sendCommand(command); 764} 765 766void AudioPolicyService::AudioCommandThread::updateAudioPatchListCommand() 767{ 768 sp<AudioCommand>command = new AudioCommand(); 769 command->mCommand = UPDATE_AUDIOPATCH_LIST; 770 ALOGV("AudioCommandThread() adding update audio patch list"); 771 sendCommand(command); 772} 773 774status_t AudioPolicyService::AudioCommandThread::setAudioPortConfigCommand( 775 const struct audio_port_config *config, int delayMs) 776{ 777 sp<AudioCommand> command = new AudioCommand(); 778 command->mCommand = SET_AUDIOPORT_CONFIG; 779 SetAudioPortConfigData *data = new SetAudioPortConfigData(); 780 data->mConfig = *config; 781 command->mParam = data; 782 command->mWaitStatus = true; 783 ALOGV("AudioCommandThread() adding set port config delay %d", delayMs); 784 return sendCommand(command, delayMs); 785} 786 787void AudioPolicyService::AudioCommandThread::dynamicPolicyMixStateUpdateCommand( 788 String8 regId, int32_t state) 789{ 790 sp<AudioCommand> command = new AudioCommand(); 791 command->mCommand = DYN_POLICY_MIX_STATE_UPDATE; 792 DynPolicyMixStateUpdateData *data = new DynPolicyMixStateUpdateData(); 793 data->mRegId = regId; 794 data->mState = state; 795 command->mParam = data; 796 ALOGV("AudioCommandThread() sending dynamic policy mix (id=%s) state update to %d", 797 regId.string(), state); 798 sendCommand(command); 799} 800 801status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs) 802{ 803 { 804 Mutex::Autolock _l(mLock); 805 insertCommand_l(command, delayMs); 806 mWaitWorkCV.signal(); 807 } 808 Mutex::Autolock _l(command->mLock); 809 while (command->mWaitStatus) { 810 nsecs_t timeOutNs = kAudioCommandTimeoutNs + milliseconds(delayMs); 811 if (command->mCond.waitRelative(command->mLock, timeOutNs) != NO_ERROR) { 812 command->mStatus = TIMED_OUT; 813 command->mWaitStatus = false; 814 } 815 } 816 return command->mStatus; 817} 818 819// insertCommand_l() must be called with mLock held 820void AudioPolicyService::AudioCommandThread::insertCommand_l(sp<AudioCommand>& command, int delayMs) 821{ 822 ssize_t i; // not size_t because i will count down to -1 823 Vector < sp<AudioCommand> > removedCommands; 824 command->mTime = systemTime() + milliseconds(delayMs); 825 826 // acquire wake lock to make sure delayed commands are processed 827 if (mAudioCommands.isEmpty()) { 828 acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string()); 829 } 830 831 // check same pending commands with later time stamps and eliminate them 832 for (i = mAudioCommands.size()-1; i >= 0; i--) { 833 sp<AudioCommand> command2 = mAudioCommands[i]; 834 // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands 835 if (command2->mTime <= command->mTime) break; 836 837 // create audio patch or release audio patch commands are equivalent 838 // with regard to filtering 839 if ((command->mCommand == CREATE_AUDIO_PATCH) || 840 (command->mCommand == RELEASE_AUDIO_PATCH)) { 841 if ((command2->mCommand != CREATE_AUDIO_PATCH) && 842 (command2->mCommand != RELEASE_AUDIO_PATCH)) { 843 continue; 844 } 845 } else if (command2->mCommand != command->mCommand) continue; 846 847 switch (command->mCommand) { 848 case SET_PARAMETERS: { 849 ParametersData *data = (ParametersData *)command->mParam.get(); 850 ParametersData *data2 = (ParametersData *)command2->mParam.get(); 851 if (data->mIO != data2->mIO) break; 852 ALOGV("Comparing parameter command %s to new command %s", 853 data2->mKeyValuePairs.string(), data->mKeyValuePairs.string()); 854 AudioParameter param = AudioParameter(data->mKeyValuePairs); 855 AudioParameter param2 = AudioParameter(data2->mKeyValuePairs); 856 for (size_t j = 0; j < param.size(); j++) { 857 String8 key; 858 String8 value; 859 param.getAt(j, key, value); 860 for (size_t k = 0; k < param2.size(); k++) { 861 String8 key2; 862 String8 value2; 863 param2.getAt(k, key2, value2); 864 if (key2 == key) { 865 param2.remove(key2); 866 ALOGV("Filtering out parameter %s", key2.string()); 867 break; 868 } 869 } 870 } 871 // if all keys have been filtered out, remove the command. 872 // otherwise, update the key value pairs 873 if (param2.size() == 0) { 874 removedCommands.add(command2); 875 } else { 876 data2->mKeyValuePairs = param2.toString(); 877 } 878 command->mTime = command2->mTime; 879 // force delayMs to non 0 so that code below does not request to wait for 880 // command status as the command is now delayed 881 delayMs = 1; 882 } break; 883 884 case SET_VOLUME: { 885 VolumeData *data = (VolumeData *)command->mParam.get(); 886 VolumeData *data2 = (VolumeData *)command2->mParam.get(); 887 if (data->mIO != data2->mIO) break; 888 if (data->mStream != data2->mStream) break; 889 ALOGV("Filtering out volume command on output %d for stream %d", 890 data->mIO, data->mStream); 891 removedCommands.add(command2); 892 command->mTime = command2->mTime; 893 // force delayMs to non 0 so that code below does not request to wait for 894 // command status as the command is now delayed 895 delayMs = 1; 896 } break; 897 898 case CREATE_AUDIO_PATCH: 899 case RELEASE_AUDIO_PATCH: { 900 audio_patch_handle_t handle; 901 struct audio_patch patch; 902 if (command->mCommand == CREATE_AUDIO_PATCH) { 903 handle = ((CreateAudioPatchData *)command->mParam.get())->mHandle; 904 patch = ((CreateAudioPatchData *)command->mParam.get())->mPatch; 905 } else { 906 handle = ((ReleaseAudioPatchData *)command->mParam.get())->mHandle; 907 } 908 audio_patch_handle_t handle2; 909 struct audio_patch patch2; 910 if (command2->mCommand == CREATE_AUDIO_PATCH) { 911 handle2 = ((CreateAudioPatchData *)command2->mParam.get())->mHandle; 912 patch2 = ((CreateAudioPatchData *)command2->mParam.get())->mPatch; 913 } else { 914 handle2 = ((ReleaseAudioPatchData *)command2->mParam.get())->mHandle; 915 } 916 if (handle != handle2) break; 917 /* Filter CREATE_AUDIO_PATCH commands only when they are issued for 918 same output. */ 919 if( (command->mCommand == CREATE_AUDIO_PATCH) && 920 (command2->mCommand == CREATE_AUDIO_PATCH) ) { 921 bool isOutputDiff = false; 922 if (patch.num_sources == patch2.num_sources) { 923 for (unsigned count = 0; count < patch.num_sources; count++) { 924 if (patch.sources[count].id != patch2.sources[count].id) { 925 isOutputDiff = true; 926 break; 927 } 928 } 929 if (isOutputDiff) 930 break; 931 } 932 } 933 ALOGV("Filtering out %s audio patch command for handle %d", 934 (command->mCommand == CREATE_AUDIO_PATCH) ? "create" : "release", handle); 935 removedCommands.add(command2); 936 command->mTime = command2->mTime; 937 // force delayMs to non 0 so that code below does not request to wait for 938 // command status as the command is now delayed 939 delayMs = 1; 940 } break; 941 942 case DYN_POLICY_MIX_STATE_UPDATE: { 943 944 } break; 945 946 case START_TONE: 947 case STOP_TONE: 948 default: 949 break; 950 } 951 } 952 953 // remove filtered commands 954 for (size_t j = 0; j < removedCommands.size(); j++) { 955 // removed commands always have time stamps greater than current command 956 for (size_t k = i + 1; k < mAudioCommands.size(); k++) { 957 if (mAudioCommands[k].get() == removedCommands[j].get()) { 958 ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand); 959 mAudioCommands.removeAt(k); 960 break; 961 } 962 } 963 } 964 removedCommands.clear(); 965 966 // Disable wait for status if delay is not 0. 967 // Except for create audio patch command because the returned patch handle 968 // is needed by audio policy manager 969 if (delayMs != 0 && command->mCommand != CREATE_AUDIO_PATCH) { 970 command->mWaitStatus = false; 971 } 972 973 // insert command at the right place according to its time stamp 974 ALOGV("inserting command: %d at index %zd, num commands %zu", 975 command->mCommand, i+1, mAudioCommands.size()); 976 mAudioCommands.insertAt(command, i + 1); 977} 978 979void AudioPolicyService::AudioCommandThread::exit() 980{ 981 ALOGV("AudioCommandThread::exit"); 982 { 983 AutoMutex _l(mLock); 984 requestExit(); 985 mWaitWorkCV.signal(); 986 } 987 requestExitAndWait(); 988} 989 990void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size) 991{ 992 snprintf(buffer, size, " %02d %06d.%03d %01u %p\n", 993 mCommand, 994 (int)ns2s(mTime), 995 (int)ns2ms(mTime)%1000, 996 mWaitStatus, 997 mParam.get()); 998} 999 1000/******* helpers for the service_ops callbacks defined below *********/ 1001void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, 1002 const char *keyValuePairs, 1003 int delayMs) 1004{ 1005 mAudioCommandThread->parametersCommand(ioHandle, keyValuePairs, 1006 delayMs); 1007} 1008 1009int AudioPolicyService::setStreamVolume(audio_stream_type_t stream, 1010 float volume, 1011 audio_io_handle_t output, 1012 int delayMs) 1013{ 1014 return (int)mAudioCommandThread->volumeCommand(stream, volume, 1015 output, delayMs); 1016} 1017 1018int AudioPolicyService::startTone(audio_policy_tone_t tone, 1019 audio_stream_type_t stream) 1020{ 1021 if (tone != AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION) { 1022 ALOGE("startTone: illegal tone requested (%d)", tone); 1023 } 1024 if (stream != AUDIO_STREAM_VOICE_CALL) { 1025 ALOGE("startTone: illegal stream (%d) requested for tone %d", stream, 1026 tone); 1027 } 1028 mTonePlaybackThread->startToneCommand(ToneGenerator::TONE_SUP_CALL_WAITING, 1029 AUDIO_STREAM_VOICE_CALL); 1030 return 0; 1031} 1032 1033int AudioPolicyService::stopTone() 1034{ 1035 mTonePlaybackThread->stopToneCommand(); 1036 return 0; 1037} 1038 1039int AudioPolicyService::setVoiceVolume(float volume, int delayMs) 1040{ 1041 return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs); 1042} 1043 1044extern "C" { 1045audio_module_handle_t aps_load_hw_module(void *service __unused, 1046 const char *name); 1047audio_io_handle_t aps_open_output(void *service __unused, 1048 audio_devices_t *pDevices, 1049 uint32_t *pSamplingRate, 1050 audio_format_t *pFormat, 1051 audio_channel_mask_t *pChannelMask, 1052 uint32_t *pLatencyMs, 1053 audio_output_flags_t flags); 1054 1055audio_io_handle_t aps_open_output_on_module(void *service __unused, 1056 audio_module_handle_t module, 1057 audio_devices_t *pDevices, 1058 uint32_t *pSamplingRate, 1059 audio_format_t *pFormat, 1060 audio_channel_mask_t *pChannelMask, 1061 uint32_t *pLatencyMs, 1062 audio_output_flags_t flags, 1063 const audio_offload_info_t *offloadInfo); 1064audio_io_handle_t aps_open_dup_output(void *service __unused, 1065 audio_io_handle_t output1, 1066 audio_io_handle_t output2); 1067int aps_close_output(void *service __unused, audio_io_handle_t output); 1068int aps_suspend_output(void *service __unused, audio_io_handle_t output); 1069int aps_restore_output(void *service __unused, audio_io_handle_t output); 1070audio_io_handle_t aps_open_input(void *service __unused, 1071 audio_devices_t *pDevices, 1072 uint32_t *pSamplingRate, 1073 audio_format_t *pFormat, 1074 audio_channel_mask_t *pChannelMask, 1075 audio_in_acoustics_t acoustics __unused); 1076audio_io_handle_t aps_open_input_on_module(void *service __unused, 1077 audio_module_handle_t module, 1078 audio_devices_t *pDevices, 1079 uint32_t *pSamplingRate, 1080 audio_format_t *pFormat, 1081 audio_channel_mask_t *pChannelMask); 1082int aps_close_input(void *service __unused, audio_io_handle_t input); 1083int aps_invalidate_stream(void *service __unused, audio_stream_type_t stream); 1084int aps_move_effects(void *service __unused, int session, 1085 audio_io_handle_t src_output, 1086 audio_io_handle_t dst_output); 1087char * aps_get_parameters(void *service __unused, audio_io_handle_t io_handle, 1088 const char *keys); 1089void aps_set_parameters(void *service, audio_io_handle_t io_handle, 1090 const char *kv_pairs, int delay_ms); 1091int aps_set_stream_volume(void *service, audio_stream_type_t stream, 1092 float volume, audio_io_handle_t output, 1093 int delay_ms); 1094int aps_start_tone(void *service, audio_policy_tone_t tone, 1095 audio_stream_type_t stream); 1096int aps_stop_tone(void *service); 1097int aps_set_voice_volume(void *service, float volume, int delay_ms); 1098}; 1099 1100namespace { 1101 struct audio_policy_service_ops aps_ops = { 1102 .open_output = aps_open_output, 1103 .open_duplicate_output = aps_open_dup_output, 1104 .close_output = aps_close_output, 1105 .suspend_output = aps_suspend_output, 1106 .restore_output = aps_restore_output, 1107 .open_input = aps_open_input, 1108 .close_input = aps_close_input, 1109 .set_stream_volume = aps_set_stream_volume, 1110 .invalidate_stream = aps_invalidate_stream, 1111 .set_parameters = aps_set_parameters, 1112 .get_parameters = aps_get_parameters, 1113 .start_tone = aps_start_tone, 1114 .stop_tone = aps_stop_tone, 1115 .set_voice_volume = aps_set_voice_volume, 1116 .move_effects = aps_move_effects, 1117 .load_hw_module = aps_load_hw_module, 1118 .open_output_on_module = aps_open_output_on_module, 1119 .open_input_on_module = aps_open_input_on_module, 1120 }; 1121}; // namespace <unnamed> 1122 1123}; // namespace android 1124