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