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