AudioPolicyService.cpp revision 3fdb1267c1623773b4eb5e1b06d5859019275e40
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#undef __STRICT_ANSI__ 21#define __STDINT_LIMITS 22#define __STDC_LIMIT_MACROS 23#include <stdint.h> 24 25#include <sys/time.h> 26#include <binder/IServiceManager.h> 27#include <utils/Log.h> 28#include <cutils/properties.h> 29#include <binder/IPCThreadState.h> 30#include <utils/String16.h> 31#include <utils/threads.h> 32#include "AudioPolicyService.h" 33#include "AudioPolicyManagerGeneric.h" 34#include <cutils/properties.h> 35#include <dlfcn.h> 36 37// ---------------------------------------------------------------------------- 38// the sim build doesn't have gettid 39 40#ifndef HAVE_GETTID 41# define gettid getpid 42#endif 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 kDumpLockSleep = 20000; 51 52static bool checkPermission() { 53#ifndef HAVE_ANDROID_OS 54 return true; 55#endif 56 if (getpid() == IPCThreadState::self()->getCallingPid()) return true; 57 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")); 58 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS"); 59 return ok; 60} 61 62// ---------------------------------------------------------------------------- 63 64AudioPolicyService::AudioPolicyService() 65 : BnAudioPolicyService() , mpPolicyManager(NULL) 66{ 67 char value[PROPERTY_VALUE_MAX]; 68 69 // start tone playback thread 70 mTonePlaybackThread = new AudioCommandThread(); 71 // start audio commands thread 72 mAudioCommandThread = new AudioCommandThread(); 73 74#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST) 75 mpPolicyManager = new AudioPolicyManagerGeneric(this); 76 LOGV("build for GENERIC_AUDIO - using generic audio policy"); 77#else 78 // if running in emulation - use the emulator driver 79 if (property_get("ro.kernel.qemu", value, 0)) { 80 LOGV("Running in emulation - using generic audio policy"); 81 mpPolicyManager = new AudioPolicyManagerGeneric(this); 82 } 83 else { 84 LOGV("Using hardware specific audio policy"); 85 mpPolicyManager = createAudioPolicyManager(this); 86 } 87#endif 88 89 // load properties 90 property_get("ro.camera.sound.forced", value, "0"); 91 mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value); 92} 93 94AudioPolicyService::~AudioPolicyService() 95{ 96 mTonePlaybackThread->exit(); 97 mTonePlaybackThread.clear(); 98 mAudioCommandThread->exit(); 99 mAudioCommandThread.clear(); 100 101 if (mpPolicyManager) { 102 delete mpPolicyManager; 103 } 104} 105 106 107status_t AudioPolicyService::setDeviceConnectionState(AudioSystem::audio_devices device, 108 AudioSystem::device_connection_state state, 109 const char *device_address) 110{ 111 if (mpPolicyManager == NULL) { 112 return NO_INIT; 113 } 114 if (!checkPermission()) { 115 return PERMISSION_DENIED; 116 } 117 if (!AudioSystem::isOutputDevice(device) && !AudioSystem::isInputDevice(device)) { 118 return BAD_VALUE; 119 } 120 if (state != AudioSystem::DEVICE_STATE_AVAILABLE && state != AudioSystem::DEVICE_STATE_UNAVAILABLE) { 121 return BAD_VALUE; 122 } 123 124 LOGV("setDeviceConnectionState() tid %d", gettid()); 125 Mutex::Autolock _l(mLock); 126 return mpPolicyManager->setDeviceConnectionState(device, state, device_address); 127} 128 129AudioSystem::device_connection_state AudioPolicyService::getDeviceConnectionState(AudioSystem::audio_devices device, 130 const char *device_address) 131{ 132 if (mpPolicyManager == NULL) { 133 return AudioSystem::DEVICE_STATE_UNAVAILABLE; 134 } 135 if (!checkPermission()) { 136 return AudioSystem::DEVICE_STATE_UNAVAILABLE; 137 } 138 return mpPolicyManager->getDeviceConnectionState(device, device_address); 139} 140 141status_t AudioPolicyService::setPhoneState(int state) 142{ 143 if (mpPolicyManager == NULL) { 144 return NO_INIT; 145 } 146 if (!checkPermission()) { 147 return PERMISSION_DENIED; 148 } 149 if (state < 0 || state >= AudioSystem::NUM_MODES) { 150 return BAD_VALUE; 151 } 152 153 LOGV("setPhoneState() tid %d", gettid()); 154 155 // TODO: check if it is more appropriate to do it in platform specific policy manager 156 AudioSystem::setMode(state); 157 158 Mutex::Autolock _l(mLock); 159 mpPolicyManager->setPhoneState(state); 160 return NO_ERROR; 161} 162 163status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask) 164{ 165 if (mpPolicyManager == NULL) { 166 return NO_INIT; 167 } 168 if (!checkPermission()) { 169 return PERMISSION_DENIED; 170 } 171 172 mpPolicyManager->setRingerMode(mode, mask); 173 return NO_ERROR; 174} 175 176status_t AudioPolicyService::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config) 177{ 178 if (mpPolicyManager == NULL) { 179 return NO_INIT; 180 } 181 if (!checkPermission()) { 182 return PERMISSION_DENIED; 183 } 184 if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) { 185 return BAD_VALUE; 186 } 187 if (config < 0 || config >= AudioSystem::NUM_FORCE_CONFIG) { 188 return BAD_VALUE; 189 } 190 LOGV("setForceUse() tid %d", gettid()); 191 Mutex::Autolock _l(mLock); 192 mpPolicyManager->setForceUse(usage, config); 193 return NO_ERROR; 194} 195 196AudioSystem::forced_config AudioPolicyService::getForceUse(AudioSystem::force_use usage) 197{ 198 if (mpPolicyManager == NULL) { 199 return AudioSystem::FORCE_NONE; 200 } 201 if (!checkPermission()) { 202 return AudioSystem::FORCE_NONE; 203 } 204 if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) { 205 return AudioSystem::FORCE_NONE; 206 } 207 return mpPolicyManager->getForceUse(usage); 208} 209 210audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream, 211 uint32_t samplingRate, 212 uint32_t format, 213 uint32_t channels, 214 AudioSystem::output_flags flags) 215{ 216 if (mpPolicyManager == NULL) { 217 return 0; 218 } 219 LOGV("getOutput() tid %d", gettid()); 220 Mutex::Autolock _l(mLock); 221 return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags); 222} 223 224status_t AudioPolicyService::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream) 225{ 226 if (mpPolicyManager == NULL) { 227 return NO_INIT; 228 } 229 LOGV("startOutput() tid %d", gettid()); 230 Mutex::Autolock _l(mLock); 231 return mpPolicyManager->startOutput(output, stream); 232} 233 234status_t AudioPolicyService::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream) 235{ 236 if (mpPolicyManager == NULL) { 237 return NO_INIT; 238 } 239 LOGV("stopOutput() tid %d", gettid()); 240 Mutex::Autolock _l(mLock); 241 return mpPolicyManager->stopOutput(output, stream); 242} 243 244void AudioPolicyService::releaseOutput(audio_io_handle_t output) 245{ 246 if (mpPolicyManager == NULL) { 247 return; 248 } 249 LOGV("releaseOutput() tid %d", gettid()); 250 Mutex::Autolock _l(mLock); 251 mpPolicyManager->releaseOutput(output); 252} 253 254audio_io_handle_t AudioPolicyService::getInput(int inputSource, 255 uint32_t samplingRate, 256 uint32_t format, 257 uint32_t channels, 258 AudioSystem::audio_in_acoustics acoustics) 259{ 260 if (mpPolicyManager == NULL) { 261 return 0; 262 } 263 Mutex::Autolock _l(mLock); 264 return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics); 265} 266 267status_t AudioPolicyService::startInput(audio_io_handle_t input) 268{ 269 if (mpPolicyManager == NULL) { 270 return NO_INIT; 271 } 272 Mutex::Autolock _l(mLock); 273 return mpPolicyManager->startInput(input); 274} 275 276status_t AudioPolicyService::stopInput(audio_io_handle_t input) 277{ 278 if (mpPolicyManager == NULL) { 279 return NO_INIT; 280 } 281 Mutex::Autolock _l(mLock); 282 return mpPolicyManager->stopInput(input); 283} 284 285void AudioPolicyService::releaseInput(audio_io_handle_t input) 286{ 287 if (mpPolicyManager == NULL) { 288 return; 289 } 290 Mutex::Autolock _l(mLock); 291 mpPolicyManager->releaseInput(input); 292} 293 294status_t AudioPolicyService::initStreamVolume(AudioSystem::stream_type stream, 295 int indexMin, 296 int indexMax) 297{ 298 if (mpPolicyManager == NULL) { 299 return NO_INIT; 300 } 301 if (!checkPermission()) { 302 return PERMISSION_DENIED; 303 } 304 if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) { 305 return BAD_VALUE; 306 } 307 mpPolicyManager->initStreamVolume(stream, indexMin, indexMax); 308 return NO_ERROR; 309} 310 311status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index) 312{ 313 if (mpPolicyManager == NULL) { 314 return NO_INIT; 315 } 316 if (!checkPermission()) { 317 return PERMISSION_DENIED; 318 } 319 if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) { 320 return BAD_VALUE; 321 } 322 323 return mpPolicyManager->setStreamVolumeIndex(stream, index); 324} 325 326status_t AudioPolicyService::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index) 327{ 328 if (mpPolicyManager == NULL) { 329 return NO_INIT; 330 } 331 if (!checkPermission()) { 332 return PERMISSION_DENIED; 333 } 334 if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) { 335 return BAD_VALUE; 336 } 337 return mpPolicyManager->getStreamVolumeIndex(stream, index); 338} 339 340void AudioPolicyService::binderDied(const wp<IBinder>& who) { 341 LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid()); 342} 343 344static bool tryLock(Mutex& mutex) 345{ 346 bool locked = false; 347 for (int i = 0; i < kDumpLockRetries; ++i) { 348 if (mutex.tryLock() == NO_ERROR) { 349 locked = true; 350 break; 351 } 352 usleep(kDumpLockSleep); 353 } 354 return locked; 355} 356 357status_t AudioPolicyService::dumpInternals(int fd) 358{ 359 const size_t SIZE = 256; 360 char buffer[SIZE]; 361 String8 result; 362 363 snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpPolicyManager); 364 result.append(buffer); 365 snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get()); 366 result.append(buffer); 367 snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get()); 368 result.append(buffer); 369 370 write(fd, result.string(), result.size()); 371 return NO_ERROR; 372} 373 374status_t AudioPolicyService::dump(int fd, const Vector<String16>& args) 375{ 376 if (checkCallingPermission(String16("android.permission.DUMP")) == false) { 377 dumpPermissionDenial(fd); 378 } else { 379 bool locked = tryLock(mLock); 380 if (!locked) { 381 String8 result(kDeadlockedString); 382 write(fd, result.string(), result.size()); 383 } 384 385 dumpInternals(fd); 386 if (mAudioCommandThread != NULL) { 387 mAudioCommandThread->dump(fd); 388 } 389 if (mTonePlaybackThread != NULL) { 390 mTonePlaybackThread->dump(fd); 391 } 392 393 if (mpPolicyManager) { 394 mpPolicyManager->dump(fd); 395 } 396 397 if (locked) mLock.unlock(); 398 } 399 return NO_ERROR; 400} 401 402status_t AudioPolicyService::dumpPermissionDenial(int fd) 403{ 404 const size_t SIZE = 256; 405 char buffer[SIZE]; 406 String8 result; 407 snprintf(buffer, SIZE, "Permission Denial: " 408 "can't dump AudioPolicyService from pid=%d, uid=%d\n", 409 IPCThreadState::self()->getCallingPid(), 410 IPCThreadState::self()->getCallingUid()); 411 result.append(buffer); 412 write(fd, result.string(), result.size()); 413 return NO_ERROR; 414} 415 416status_t AudioPolicyService::onTransact( 417 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 418{ 419 return BnAudioPolicyService::onTransact(code, data, reply, flags); 420} 421 422 423// ---------------------------------------------------------------------------- 424void AudioPolicyService::instantiate() { 425 defaultServiceManager()->addService( 426 String16("media.audio_policy"), new AudioPolicyService()); 427} 428 429 430// ---------------------------------------------------------------------------- 431// AudioPolicyClientInterface implementation 432// ---------------------------------------------------------------------------- 433 434 435audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices, 436 uint32_t *pSamplingRate, 437 uint32_t *pFormat, 438 uint32_t *pChannels, 439 uint32_t *pLatencyMs, 440 AudioSystem::output_flags flags) 441{ 442 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 443 if (af == 0) { 444 LOGW("openOutput() could not get AudioFlinger"); 445 return 0; 446 } 447 448 return af->openOutput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, pLatencyMs, flags); 449} 450 451audio_io_handle_t AudioPolicyService::openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2) 452{ 453 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 454 if (af == 0) { 455 LOGW("openDuplicateOutput() could not get AudioFlinger"); 456 return 0; 457 } 458 return af->openDuplicateOutput(output1, output2); 459} 460 461status_t AudioPolicyService::closeOutput(audio_io_handle_t output) 462{ 463 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 464 if (af == 0) return PERMISSION_DENIED; 465 466 return af->closeOutput(output); 467} 468 469 470status_t AudioPolicyService::suspendOutput(audio_io_handle_t output) 471{ 472 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 473 if (af == 0) { 474 LOGW("suspendOutput() could not get AudioFlinger"); 475 return PERMISSION_DENIED; 476 } 477 478 return af->suspendOutput(output); 479} 480 481status_t AudioPolicyService::restoreOutput(audio_io_handle_t output) 482{ 483 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 484 if (af == 0) { 485 LOGW("restoreOutput() could not get AudioFlinger"); 486 return PERMISSION_DENIED; 487 } 488 489 return af->restoreOutput(output); 490} 491 492audio_io_handle_t AudioPolicyService::openInput(uint32_t *pDevices, 493 uint32_t *pSamplingRate, 494 uint32_t *pFormat, 495 uint32_t *pChannels, 496 uint32_t acoustics) 497{ 498 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 499 if (af == 0) { 500 LOGW("openInput() could not get AudioFlinger"); 501 return 0; 502 } 503 504 return af->openInput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, acoustics); 505} 506 507status_t AudioPolicyService::closeInput(audio_io_handle_t input) 508{ 509 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 510 if (af == 0) return PERMISSION_DENIED; 511 512 return af->closeInput(input); 513} 514 515status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs) 516{ 517 return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs); 518} 519 520status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output) 521{ 522 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 523 if (af == 0) return PERMISSION_DENIED; 524 525 return af->setStreamOutput(stream, output); 526} 527 528 529void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs) 530{ 531 mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs); 532} 533 534String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys) 535{ 536 String8 result = AudioSystem::getParameters(ioHandle, keys); 537 return result; 538} 539 540status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream) 541{ 542 mTonePlaybackThread->startToneCommand(tone, stream); 543 return NO_ERROR; 544} 545 546status_t AudioPolicyService::stopTone() 547{ 548 mTonePlaybackThread->stopToneCommand(); 549 return NO_ERROR; 550} 551 552status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs) 553{ 554 return mAudioCommandThread->voiceVolumeCommand(volume, delayMs); 555} 556 557// ----------- AudioPolicyService::AudioCommandThread implementation ---------- 558 559AudioPolicyService::AudioCommandThread::AudioCommandThread() 560 : Thread(false) 561{ 562 mpToneGenerator = NULL; 563} 564 565 566AudioPolicyService::AudioCommandThread::~AudioCommandThread() 567{ 568 mAudioCommands.clear(); 569 if (mpToneGenerator != NULL) delete mpToneGenerator; 570} 571 572void AudioPolicyService::AudioCommandThread::onFirstRef() 573{ 574 const size_t SIZE = 256; 575 char buffer[SIZE]; 576 577 snprintf(buffer, SIZE, "AudioCommandThread"); 578 579 run(buffer, ANDROID_PRIORITY_AUDIO); 580} 581 582bool AudioPolicyService::AudioCommandThread::threadLoop() 583{ 584 nsecs_t waitTime = INT64_MAX; 585 586 mLock.lock(); 587 while (!exitPending()) 588 { 589 while(!mAudioCommands.isEmpty()) { 590 nsecs_t curTime = systemTime(); 591 // commands are sorted by increasing time stamp: execute them from index 0 and up 592 if (mAudioCommands[0]->mTime <= curTime) { 593 AudioCommand *command = mAudioCommands[0]; 594 mAudioCommands.removeAt(0); 595 mLastCommand = *command; 596 597 switch (command->mCommand) { 598 case START_TONE: { 599 mLock.unlock(); 600 ToneData *data = (ToneData *)command->mParam; 601 LOGV("AudioCommandThread() processing start tone %d on stream %d", 602 data->mType, data->mStream); 603 if (mpToneGenerator != NULL) 604 delete mpToneGenerator; 605 mpToneGenerator = new ToneGenerator(data->mStream, 1.0); 606 mpToneGenerator->startTone(data->mType); 607 delete data; 608 mLock.lock(); 609 }break; 610 case STOP_TONE: { 611 mLock.unlock(); 612 LOGV("AudioCommandThread() processing stop tone"); 613 if (mpToneGenerator != NULL) { 614 mpToneGenerator->stopTone(); 615 delete mpToneGenerator; 616 mpToneGenerator = NULL; 617 } 618 mLock.lock(); 619 }break; 620 case SET_VOLUME: { 621 VolumeData *data = (VolumeData *)command->mParam; 622 LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO); 623 command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO); 624 if (command->mWaitStatus) { 625 command->mCond.signal(); 626 mWaitWorkCV.wait(mLock); 627 } 628 delete data; 629 }break; 630 case SET_PARAMETERS: { 631 ParametersData *data = (ParametersData *)command->mParam; 632 LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO); 633 command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs); 634 if (command->mWaitStatus) { 635 command->mCond.signal(); 636 mWaitWorkCV.wait(mLock); 637 } 638 delete data; 639 }break; 640 case SET_VOICE_VOLUME: { 641 VoiceVolumeData *data = (VoiceVolumeData *)command->mParam; 642 LOGV("AudioCommandThread() processing set voice volume volume %f", data->mVolume); 643 command->mStatus = AudioSystem::setVoiceVolume(data->mVolume); 644 if (command->mWaitStatus) { 645 command->mCond.signal(); 646 mWaitWorkCV.wait(mLock); 647 } 648 delete data; 649 }break; 650 default: 651 LOGW("AudioCommandThread() unknown command %d", command->mCommand); 652 } 653 delete command; 654 waitTime = INT64_MAX; 655 } else { 656 waitTime = mAudioCommands[0]->mTime - curTime; 657 break; 658 } 659 } 660 LOGV("AudioCommandThread() going to sleep"); 661 mWaitWorkCV.waitRelative(mLock, waitTime); 662 LOGV("AudioCommandThread() waking up"); 663 } 664 mLock.unlock(); 665 return false; 666} 667 668status_t AudioPolicyService::AudioCommandThread::dump(int fd) 669{ 670 const size_t SIZE = 256; 671 char buffer[SIZE]; 672 String8 result; 673 674 snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this); 675 result.append(buffer); 676 write(fd, result.string(), result.size()); 677 678 bool locked = tryLock(mLock); 679 if (!locked) { 680 String8 result2(kCmdDeadlockedString); 681 write(fd, result2.string(), result2.size()); 682 } 683 684 snprintf(buffer, SIZE, "- Commands:\n"); 685 result = String8(buffer); 686 result.append(" Command Time Wait pParam\n"); 687 for (int i = 0; i < (int)mAudioCommands.size(); i++) { 688 mAudioCommands[i]->dump(buffer, SIZE); 689 result.append(buffer); 690 } 691 result.append(" Last Command\n"); 692 mLastCommand.dump(buffer, SIZE); 693 result.append(buffer); 694 695 write(fd, result.string(), result.size()); 696 697 if (locked) mLock.unlock(); 698 699 return NO_ERROR; 700} 701 702void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream) 703{ 704 AudioCommand *command = new AudioCommand(); 705 command->mCommand = START_TONE; 706 ToneData *data = new ToneData(); 707 data->mType = type; 708 data->mStream = stream; 709 command->mParam = (void *)data; 710 command->mWaitStatus = false; 711 Mutex::Autolock _l(mLock); 712 insertCommand_l(command); 713 LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream); 714 mWaitWorkCV.signal(); 715} 716 717void AudioPolicyService::AudioCommandThread::stopToneCommand() 718{ 719 AudioCommand *command = new AudioCommand(); 720 command->mCommand = STOP_TONE; 721 command->mParam = NULL; 722 command->mWaitStatus = false; 723 Mutex::Autolock _l(mLock); 724 insertCommand_l(command); 725 LOGV("AudioCommandThread() adding tone stop"); 726 mWaitWorkCV.signal(); 727} 728 729status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs) 730{ 731 status_t status = NO_ERROR; 732 733 AudioCommand *command = new AudioCommand(); 734 command->mCommand = SET_VOLUME; 735 VolumeData *data = new VolumeData(); 736 data->mStream = stream; 737 data->mVolume = volume; 738 data->mIO = output; 739 command->mParam = data; 740 if (delayMs == 0) { 741 command->mWaitStatus = true; 742 } else { 743 command->mWaitStatus = false; 744 } 745 Mutex::Autolock _l(mLock); 746 insertCommand_l(command, delayMs); 747 LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output); 748 mWaitWorkCV.signal(); 749 if (command->mWaitStatus) { 750 command->mCond.wait(mLock); 751 status = command->mStatus; 752 mWaitWorkCV.signal(); 753 } 754 return status; 755} 756 757status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs) 758{ 759 status_t status = NO_ERROR; 760 761 AudioCommand *command = new AudioCommand(); 762 command->mCommand = SET_PARAMETERS; 763 ParametersData *data = new ParametersData(); 764 data->mIO = ioHandle; 765 data->mKeyValuePairs = keyValuePairs; 766 command->mParam = data; 767 if (delayMs == 0) { 768 command->mWaitStatus = true; 769 } else { 770 command->mWaitStatus = false; 771 } 772 Mutex::Autolock _l(mLock); 773 insertCommand_l(command, delayMs); 774 LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs); 775 mWaitWorkCV.signal(); 776 if (command->mWaitStatus) { 777 command->mCond.wait(mLock); 778 status = command->mStatus; 779 mWaitWorkCV.signal(); 780 } 781 return status; 782} 783 784status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs) 785{ 786 status_t status = NO_ERROR; 787 788 AudioCommand *command = new AudioCommand(); 789 command->mCommand = SET_VOICE_VOLUME; 790 VoiceVolumeData *data = new VoiceVolumeData(); 791 data->mVolume = volume; 792 command->mParam = data; 793 if (delayMs == 0) { 794 command->mWaitStatus = true; 795 } else { 796 command->mWaitStatus = false; 797 } 798 Mutex::Autolock _l(mLock); 799 insertCommand_l(command, delayMs); 800 LOGV("AudioCommandThread() adding set voice volume volume %f", volume); 801 mWaitWorkCV.signal(); 802 if (command->mWaitStatus) { 803 command->mCond.wait(mLock); 804 status = command->mStatus; 805 mWaitWorkCV.signal(); 806 } 807 return status; 808} 809 810// insertCommand_l() must be called with mLock held 811void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs) 812{ 813 ssize_t i; 814 Vector <AudioCommand *> removedCommands; 815 816 command->mTime = systemTime() + milliseconds(delayMs); 817 818 // check same pending commands with later time stamps and eliminate them 819 for (i = mAudioCommands.size()-1; i >= 0; i--) { 820 AudioCommand *command2 = mAudioCommands[i]; 821 // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands 822 if (command2->mTime <= command->mTime) break; 823 if (command2->mCommand != command->mCommand) continue; 824 825 switch (command->mCommand) { 826 case SET_PARAMETERS: { 827 ParametersData *data = (ParametersData *)command->mParam; 828 ParametersData *data2 = (ParametersData *)command2->mParam; 829 if (data->mIO != data2->mIO) break; 830 LOGV("Comparing parameter command %s to new command %s", data2->mKeyValuePairs.string(), data->mKeyValuePairs.string()); 831 AudioParameter param = AudioParameter(data->mKeyValuePairs); 832 AudioParameter param2 = AudioParameter(data2->mKeyValuePairs); 833 for (size_t j = 0; j < param.size(); j++) { 834 String8 key; 835 String8 value; 836 param.getAt(j, key, value); 837 for (size_t k = 0; k < param2.size(); k++) { 838 String8 key2; 839 String8 value2; 840 param2.getAt(k, key2, value2); 841 if (key2 == key) { 842 param2.remove(key2); 843 LOGV("Filtering out parameter %s", key2.string()); 844 break; 845 } 846 } 847 } 848 // if all keys have been filtered out, remove the command. 849 // otherwise, update the key value pairs 850 if (param2.size() == 0) { 851 removedCommands.add(command2); 852 } else { 853 data2->mKeyValuePairs = param2.toString(); 854 } 855 } break; 856 857 case SET_VOLUME: { 858 VolumeData *data = (VolumeData *)command->mParam; 859 VolumeData *data2 = (VolumeData *)command2->mParam; 860 if (data->mIO != data2->mIO) break; 861 if (data->mStream != data2->mStream) break; 862 LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream); 863 removedCommands.add(command2); 864 } break; 865 case START_TONE: 866 case STOP_TONE: 867 default: 868 break; 869 } 870 } 871 872 // remove filtered commands 873 for (size_t j = 0; j < removedCommands.size(); j++) { 874 // removed commands always have time stamps greater than current command 875 for (size_t k = i + 1; k < mAudioCommands.size(); k++) { 876 if (mAudioCommands[k] == removedCommands[j]) { 877 LOGV("suppressing command: %d", mAudioCommands[k]->mCommand); 878 mAudioCommands.removeAt(k); 879 break; 880 } 881 } 882 } 883 removedCommands.clear(); 884 885 // insert command at the right place according to its time stamp 886 LOGV("inserting command: %d at index %ld, num commands %d", command->mCommand, i+1, mAudioCommands.size()); 887 mAudioCommands.insertAt(command, i + 1); 888} 889 890void AudioPolicyService::AudioCommandThread::exit() 891{ 892 LOGV("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); 909} 910 911}; // namespace android 912