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