AudioPolicyService.cpp revision 4980df29f61d5fad95e17ca1d1969f6ca4c1f296
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 <binder/ActivityManager.h> 32#include <binder/PermissionController.h> 33#include <binder/IResultReceiver.h> 34#include <utils/String16.h> 35#include <utils/threads.h> 36#include "AudioPolicyService.h" 37#include "ServiceUtilities.h" 38#include <hardware_legacy/power.h> 39#include <media/AudioEffect.h> 40#include <media/AudioParameter.h> 41 42#include <system/audio.h> 43#include <system/audio_policy.h> 44 45#include <private/android_filesystem_config.h> 46 47namespace android { 48 49static const char kDeadlockedString[] = "AudioPolicyService may be deadlocked\n"; 50static const char kCmdDeadlockedString[] = "AudioPolicyService command thread may be deadlocked\n"; 51 52static const int kDumpLockRetries = 50; 53static const int kDumpLockSleepUs = 20000; 54 55static const nsecs_t kAudioCommandTimeoutNs = seconds(3); // 3 seconds 56 57static const String16 sManageAudioPolicyPermission("android.permission.MANAGE_AUDIO_POLICY"); 58 59// ---------------------------------------------------------------------------- 60 61AudioPolicyService::AudioPolicyService() 62 : BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL), 63 mAudioPolicyManager(NULL), mAudioPolicyClient(NULL), mPhoneState(AUDIO_MODE_INVALID) 64{ 65} 66 67void AudioPolicyService::onFirstRef() 68{ 69 { 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 mAudioPolicyClient = new AudioPolicyClient(this); 80 mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient); 81 } 82 // load audio processing modules 83 sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects(); 84 { 85 Mutex::Autolock _l(mLock); 86 mAudioPolicyEffects = audioPolicyEffects; 87 } 88 89 mUidPolicy = new UidPolicy(this); 90 mUidPolicy->registerSelf(); 91} 92 93AudioPolicyService::~AudioPolicyService() 94{ 95 mTonePlaybackThread->exit(); 96 mAudioCommandThread->exit(); 97 mOutputCommandThread->exit(); 98 99 destroyAudioPolicyManager(mAudioPolicyManager); 100 delete mAudioPolicyClient; 101 102 mNotificationClients.clear(); 103 mAudioPolicyEffects.clear(); 104 105 mUidPolicy->unregisterSelf(); 106 mUidPolicy.clear(); 107} 108 109// A notification client is always registered by AudioSystem when the client process 110// connects to AudioPolicyService. 111void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client) 112{ 113 if (client == 0) { 114 ALOGW("%s got NULL client", __FUNCTION__); 115 return; 116 } 117 Mutex::Autolock _l(mNotificationClientsLock); 118 119 uid_t uid = IPCThreadState::self()->getCallingUid(); 120 if (mNotificationClients.indexOfKey(uid) < 0) { 121 sp<NotificationClient> notificationClient = new NotificationClient(this, 122 client, 123 uid); 124 ALOGV("registerClient() client %p, uid %d", client.get(), uid); 125 126 mNotificationClients.add(uid, notificationClient); 127 128 sp<IBinder> binder = IInterface::asBinder(client); 129 binder->linkToDeath(notificationClient); 130 } 131} 132 133void AudioPolicyService::setAudioPortCallbacksEnabled(bool enabled) 134{ 135 Mutex::Autolock _l(mNotificationClientsLock); 136 137 uid_t uid = IPCThreadState::self()->getCallingUid(); 138 if (mNotificationClients.indexOfKey(uid) < 0) { 139 return; 140 } 141 mNotificationClients.valueFor(uid)->setAudioPortCallbacksEnabled(enabled); 142} 143 144// removeNotificationClient() is called when the client process dies. 145void AudioPolicyService::removeNotificationClient(uid_t uid) 146{ 147 { 148 Mutex::Autolock _l(mNotificationClientsLock); 149 mNotificationClients.removeItem(uid); 150 } 151 { 152 Mutex::Autolock _l(mLock); 153 if (mAudioPolicyManager) { 154 mAudioPolicyManager->releaseResourcesForUid(uid); 155 } 156 } 157} 158 159void AudioPolicyService::onAudioPortListUpdate() 160{ 161 mOutputCommandThread->updateAudioPortListCommand(); 162} 163 164void AudioPolicyService::doOnAudioPortListUpdate() 165{ 166 Mutex::Autolock _l(mNotificationClientsLock); 167 for (size_t i = 0; i < mNotificationClients.size(); i++) { 168 mNotificationClients.valueAt(i)->onAudioPortListUpdate(); 169 } 170} 171 172void AudioPolicyService::onAudioPatchListUpdate() 173{ 174 mOutputCommandThread->updateAudioPatchListCommand(); 175} 176 177void AudioPolicyService::doOnAudioPatchListUpdate() 178{ 179 Mutex::Autolock _l(mNotificationClientsLock); 180 for (size_t i = 0; i < mNotificationClients.size(); i++) { 181 mNotificationClients.valueAt(i)->onAudioPatchListUpdate(); 182 } 183} 184 185void AudioPolicyService::onDynamicPolicyMixStateUpdate(const String8& regId, int32_t state) 186{ 187 ALOGV("AudioPolicyService::onDynamicPolicyMixStateUpdate(%s, %d)", 188 regId.string(), state); 189 mOutputCommandThread->dynamicPolicyMixStateUpdateCommand(regId, state); 190} 191 192void AudioPolicyService::doOnDynamicPolicyMixStateUpdate(const String8& regId, int32_t state) 193{ 194 Mutex::Autolock _l(mNotificationClientsLock); 195 for (size_t i = 0; i < mNotificationClients.size(); i++) { 196 mNotificationClients.valueAt(i)->onDynamicPolicyMixStateUpdate(regId, state); 197 } 198} 199 200void AudioPolicyService::onRecordingConfigurationUpdate(int event, 201 const record_client_info_t *clientInfo, const audio_config_base_t *clientConfig, 202 const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle) 203{ 204 mOutputCommandThread->recordingConfigurationUpdateCommand(event, clientInfo, 205 clientConfig, deviceConfig, patchHandle); 206} 207 208void AudioPolicyService::doOnRecordingConfigurationUpdate(int event, 209 const record_client_info_t *clientInfo, const audio_config_base_t *clientConfig, 210 const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle) 211{ 212 Mutex::Autolock _l(mNotificationClientsLock); 213 for (size_t i = 0; i < mNotificationClients.size(); i++) { 214 mNotificationClients.valueAt(i)->onRecordingConfigurationUpdate(event, clientInfo, 215 clientConfig, deviceConfig, patchHandle); 216 } 217} 218 219status_t AudioPolicyService::clientCreateAudioPatch(const struct audio_patch *patch, 220 audio_patch_handle_t *handle, 221 int delayMs) 222{ 223 return mAudioCommandThread->createAudioPatchCommand(patch, handle, delayMs); 224} 225 226status_t AudioPolicyService::clientReleaseAudioPatch(audio_patch_handle_t handle, 227 int delayMs) 228{ 229 return mAudioCommandThread->releaseAudioPatchCommand(handle, delayMs); 230} 231 232status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_config *config, 233 int delayMs) 234{ 235 return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs); 236} 237 238AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service, 239 const sp<IAudioPolicyServiceClient>& client, 240 uid_t uid) 241 : mService(service), mUid(uid), mAudioPolicyServiceClient(client), 242 mAudioPortCallbacksEnabled(false) 243{ 244} 245 246AudioPolicyService::NotificationClient::~NotificationClient() 247{ 248} 249 250void AudioPolicyService::NotificationClient::binderDied(const wp<IBinder>& who __unused) 251{ 252 sp<NotificationClient> keep(this); 253 sp<AudioPolicyService> service = mService.promote(); 254 if (service != 0) { 255 service->removeNotificationClient(mUid); 256 } 257} 258 259void AudioPolicyService::NotificationClient::onAudioPortListUpdate() 260{ 261 if (mAudioPolicyServiceClient != 0 && mAudioPortCallbacksEnabled) { 262 mAudioPolicyServiceClient->onAudioPortListUpdate(); 263 } 264} 265 266void AudioPolicyService::NotificationClient::onAudioPatchListUpdate() 267{ 268 if (mAudioPolicyServiceClient != 0 && mAudioPortCallbacksEnabled) { 269 mAudioPolicyServiceClient->onAudioPatchListUpdate(); 270 } 271} 272 273void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate( 274 const String8& regId, int32_t state) 275{ 276 if (mAudioPolicyServiceClient != 0 && mUid < AID_APP_START) { 277 mAudioPolicyServiceClient->onDynamicPolicyMixStateUpdate(regId, state); 278 } 279} 280 281void AudioPolicyService::NotificationClient::onRecordingConfigurationUpdate( 282 int event, const record_client_info_t *clientInfo, 283 const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig, 284 audio_patch_handle_t patchHandle) 285{ 286 if (mAudioPolicyServiceClient != 0 && mUid < AID_APP_START) { 287 mAudioPolicyServiceClient->onRecordingConfigurationUpdate(event, clientInfo, 288 clientConfig, deviceConfig, patchHandle); 289 } 290} 291 292void AudioPolicyService::NotificationClient::setAudioPortCallbacksEnabled(bool enabled) 293{ 294 mAudioPortCallbacksEnabled = enabled; 295} 296 297 298void AudioPolicyService::binderDied(const wp<IBinder>& who) { 299 ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(), 300 IPCThreadState::self()->getCallingPid()); 301} 302 303static bool tryLock(Mutex& mutex) 304{ 305 bool locked = false; 306 for (int i = 0; i < kDumpLockRetries; ++i) { 307 if (mutex.tryLock() == NO_ERROR) { 308 locked = true; 309 break; 310 } 311 usleep(kDumpLockSleepUs); 312 } 313 return locked; 314} 315 316status_t AudioPolicyService::dumpInternals(int fd) 317{ 318 const size_t SIZE = 256; 319 char buffer[SIZE]; 320 String8 result; 321 322 snprintf(buffer, SIZE, "AudioPolicyManager: %p\n", mAudioPolicyManager); 323 result.append(buffer); 324 snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get()); 325 result.append(buffer); 326 snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get()); 327 result.append(buffer); 328 329 write(fd, result.string(), result.size()); 330 return NO_ERROR; 331} 332 333void AudioPolicyService::setRecordSilenced(uid_t uid, bool silenced) 334{ 335 { 336 Mutex::Autolock _l(mLock); 337 if (mAudioPolicyManager) { 338 mAudioPolicyManager->setRecordSilenced(uid, silenced); 339 } 340 } 341 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 342 if (af) { 343 af->setRecordSilenced(uid, silenced); 344 } 345} 346 347status_t AudioPolicyService::dump(int fd, const Vector<String16>& args __unused) 348{ 349 if (!dumpAllowed()) { 350 dumpPermissionDenial(fd); 351 } else { 352 bool locked = tryLock(mLock); 353 if (!locked) { 354 String8 result(kDeadlockedString); 355 write(fd, result.string(), result.size()); 356 } 357 358 dumpInternals(fd); 359 if (mAudioCommandThread != 0) { 360 mAudioCommandThread->dump(fd); 361 } 362 if (mTonePlaybackThread != 0) { 363 mTonePlaybackThread->dump(fd); 364 } 365 366 if (mAudioPolicyManager) { 367 mAudioPolicyManager->dump(fd); 368 } 369 370 if (locked) mLock.unlock(); 371 } 372 return NO_ERROR; 373} 374 375status_t AudioPolicyService::dumpPermissionDenial(int fd) 376{ 377 const size_t SIZE = 256; 378 char buffer[SIZE]; 379 String8 result; 380 snprintf(buffer, SIZE, "Permission Denial: " 381 "can't dump AudioPolicyService from pid=%d, uid=%d\n", 382 IPCThreadState::self()->getCallingPid(), 383 IPCThreadState::self()->getCallingUid()); 384 result.append(buffer); 385 write(fd, result.string(), result.size()); 386 return NO_ERROR; 387} 388 389status_t AudioPolicyService::onTransact( 390 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { 391 switch (code) { 392 case SHELL_COMMAND_TRANSACTION: { 393 int in = data.readFileDescriptor(); 394 int out = data.readFileDescriptor(); 395 int err = data.readFileDescriptor(); 396 int argc = data.readInt32(); 397 Vector<String16> args; 398 for (int i = 0; i < argc && data.dataAvail() > 0; i++) { 399 args.add(data.readString16()); 400 } 401 sp<IBinder> unusedCallback; 402 sp<IResultReceiver> resultReceiver; 403 status_t status; 404 if ((status = data.readNullableStrongBinder(&unusedCallback)) != NO_ERROR) { 405 return status; 406 } 407 if ((status = data.readNullableStrongBinder(&resultReceiver)) != NO_ERROR) { 408 return status; 409 } 410 status = shellCommand(in, out, err, args); 411 if (resultReceiver != nullptr) { 412 resultReceiver->send(status); 413 } 414 return NO_ERROR; 415 } 416 } 417 418 return BnAudioPolicyService::onTransact(code, data, reply, flags); 419} 420 421// ------------------- Shell command implementation ------------------- 422 423// NOTE: This is a remote API - make sure all args are validated 424status_t AudioPolicyService::shellCommand(int in, int out, int err, Vector<String16>& args) { 425 if (!checkCallingPermission(sManageAudioPolicyPermission, nullptr, nullptr)) { 426 return PERMISSION_DENIED; 427 } 428 if (in == BAD_TYPE || out == BAD_TYPE || err == BAD_TYPE) { 429 return BAD_VALUE; 430 } 431 if (args.size() == 3 && args[0] == String16("set-uid-state")) { 432 return handleSetUidState(args, err); 433 } else if (args.size() == 2 && args[0] == String16("reset-uid-state")) { 434 return handleResetUidState(args, err); 435 } else if (args.size() == 2 && args[0] == String16("get-uid-state")) { 436 return handleGetUidState(args, out, err); 437 } else if (args.size() == 1 && args[0] == String16("help")) { 438 printHelp(out); 439 return NO_ERROR; 440 } 441 printHelp(err); 442 return BAD_VALUE; 443} 444 445status_t AudioPolicyService::handleSetUidState(Vector<String16>& args, int err) { 446 PermissionController pc; 447 int uid = pc.getPackageUid(args[1], 0); 448 if (uid <= 0) { 449 ALOGE("Unknown package: '%s'", String8(args[1]).string()); 450 dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string()); 451 return BAD_VALUE; 452 } 453 bool active = false; 454 if (args[2] == String16("active")) { 455 active = true; 456 } else if ((args[2] != String16("idle"))) { 457 ALOGE("Expected active or idle but got: '%s'", String8(args[2]).string()); 458 return BAD_VALUE; 459 } 460 mUidPolicy->addOverrideUid(uid, active); 461 return NO_ERROR; 462} 463 464status_t AudioPolicyService::handleResetUidState(Vector<String16>& args, int err) { 465 PermissionController pc; 466 int uid = pc.getPackageUid(args[1], 0); 467 if (uid < 0) { 468 ALOGE("Unknown package: '%s'", String8(args[1]).string()); 469 dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string()); 470 return BAD_VALUE; 471 } 472 mUidPolicy->removeOverrideUid(uid); 473 return NO_ERROR; 474} 475 476status_t AudioPolicyService::handleGetUidState(Vector<String16>& args, int out, int err) { 477 PermissionController pc; 478 int uid = pc.getPackageUid(args[1], 0); 479 if (uid < 0) { 480 ALOGE("Unknown package: '%s'", String8(args[1]).string()); 481 dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string()); 482 return BAD_VALUE; 483 } 484 if (mUidPolicy->isUidActive(uid)) { 485 return dprintf(out, "active\n"); 486 } else { 487 return dprintf(out, "idle\n"); 488 } 489} 490 491status_t AudioPolicyService::printHelp(int out) { 492 return dprintf(out, "Audio policy service commands:\n" 493 " get-uid-state <PACKAGE> gets the uid state\n" 494 " set-uid-state <PACKAGE> <active|idle> overrides the uid state\n" 495 " reset-uid-state <PACKAGE> clears the uid state override\n" 496 " help print this message\n"); 497} 498 499// ----------- AudioPolicyService::UidPolicy implementation ---------- 500 501void AudioPolicyService::UidPolicy::registerSelf() { 502 ActivityManager am; 503 am.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE 504 | ActivityManager::UID_OBSERVER_IDLE 505 | ActivityManager::UID_OBSERVER_ACTIVE, 506 ActivityManager::PROCESS_STATE_UNKNOWN, 507 String16("audioserver")); 508} 509 510void AudioPolicyService::UidPolicy::unregisterSelf() { 511 ActivityManager am; 512 am.unregisterUidObserver(this); 513} 514 515void AudioPolicyService::UidPolicy::onUidGone(uid_t uid, __unused bool disabled) { 516 onUidIdle(uid, disabled); 517} 518 519void AudioPolicyService::UidPolicy::onUidActive(uid_t uid) { 520 { 521 Mutex::Autolock _l(mUidLock); 522 mActiveUids.insert(uid); 523 } 524 sp<AudioPolicyService> service = mService.promote(); 525 if (service != nullptr) { 526 service->setRecordSilenced(uid, false); 527 } 528} 529 530void AudioPolicyService::UidPolicy::onUidIdle(uid_t uid, __unused bool disabled) { 531 bool deleted = false; 532 { 533 Mutex::Autolock _l(mUidLock); 534 if (mActiveUids.erase(uid) > 0) { 535 deleted = true; 536 } 537 } 538 if (deleted) { 539 sp<AudioPolicyService> service = mService.promote(); 540 if (service != nullptr) { 541 service->setRecordSilenced(uid, true); 542 } 543 } 544} 545 546void AudioPolicyService::UidPolicy::addOverrideUid(uid_t uid, bool active) { 547 updateOverrideUid(uid, active, true); 548} 549 550void AudioPolicyService::UidPolicy::removeOverrideUid(uid_t uid) { 551 updateOverrideUid(uid, false, false); 552} 553 554void AudioPolicyService::UidPolicy::updateOverrideUid(uid_t uid, bool active, bool insert) { 555 bool wasActive = false; 556 bool isActive = false; 557 { 558 Mutex::Autolock _l(mUidLock); 559 wasActive = isUidActiveLocked(uid); 560 mOverrideUids.erase(uid); 561 if (insert) { 562 mOverrideUids.insert(std::pair<uid_t, bool>(uid, active)); 563 } 564 isActive = isUidActiveLocked(uid); 565 } 566 if (wasActive != isActive) { 567 sp<AudioPolicyService> service = mService.promote(); 568 if (service != nullptr) { 569 service->setRecordSilenced(uid, !isActive); 570 } 571 } 572} 573 574bool AudioPolicyService::UidPolicy::isUidActive(uid_t uid) { 575 // Non-app UIDs are considered always active 576 if (uid < FIRST_APPLICATION_UID) { 577 return true; 578 } 579 Mutex::Autolock _l(mUidLock); 580 return isUidActiveLocked(uid); 581} 582 583bool AudioPolicyService::UidPolicy::isUidActiveLocked(uid_t uid) { 584 // Non-app UIDs are considered always active 585 if (uid < FIRST_APPLICATION_UID) { 586 return true; 587 } 588 auto it = mOverrideUids.find(uid); 589 if (it != mOverrideUids.end()) { 590 return it->second; 591 } 592 return mActiveUids.find(uid) != mActiveUids.end(); 593} 594 595// ----------- AudioPolicyService::AudioCommandThread implementation ---------- 596 597AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name, 598 const wp<AudioPolicyService>& service) 599 : Thread(false), mName(name), mService(service) 600{ 601 mpToneGenerator = NULL; 602} 603 604 605AudioPolicyService::AudioCommandThread::~AudioCommandThread() 606{ 607 if (!mAudioCommands.isEmpty()) { 608 release_wake_lock(mName.string()); 609 } 610 mAudioCommands.clear(); 611 delete mpToneGenerator; 612} 613 614void AudioPolicyService::AudioCommandThread::onFirstRef() 615{ 616 run(mName.string(), ANDROID_PRIORITY_AUDIO); 617} 618 619bool AudioPolicyService::AudioCommandThread::threadLoop() 620{ 621 nsecs_t waitTime = -1; 622 623 mLock.lock(); 624 while (!exitPending()) 625 { 626 sp<AudioPolicyService> svc; 627 while (!mAudioCommands.isEmpty() && !exitPending()) { 628 nsecs_t curTime = systemTime(); 629 // commands are sorted by increasing time stamp: execute them from index 0 and up 630 if (mAudioCommands[0]->mTime <= curTime) { 631 sp<AudioCommand> command = mAudioCommands[0]; 632 mAudioCommands.removeAt(0); 633 mLastCommand = command; 634 635 switch (command->mCommand) { 636 case START_TONE: { 637 mLock.unlock(); 638 ToneData *data = (ToneData *)command->mParam.get(); 639 ALOGV("AudioCommandThread() processing start tone %d on stream %d", 640 data->mType, data->mStream); 641 delete mpToneGenerator; 642 mpToneGenerator = new ToneGenerator(data->mStream, 1.0); 643 mpToneGenerator->startTone(data->mType); 644 mLock.lock(); 645 }break; 646 case STOP_TONE: { 647 mLock.unlock(); 648 ALOGV("AudioCommandThread() processing stop tone"); 649 if (mpToneGenerator != NULL) { 650 mpToneGenerator->stopTone(); 651 delete mpToneGenerator; 652 mpToneGenerator = NULL; 653 } 654 mLock.lock(); 655 }break; 656 case SET_VOLUME: { 657 VolumeData *data = (VolumeData *)command->mParam.get(); 658 ALOGV("AudioCommandThread() processing set volume stream %d, \ 659 volume %f, output %d", data->mStream, data->mVolume, data->mIO); 660 command->mStatus = AudioSystem::setStreamVolume(data->mStream, 661 data->mVolume, 662 data->mIO); 663 }break; 664 case SET_PARAMETERS: { 665 ParametersData *data = (ParametersData *)command->mParam.get(); 666 ALOGV("AudioCommandThread() processing set parameters string %s, io %d", 667 data->mKeyValuePairs.string(), data->mIO); 668 command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs); 669 }break; 670 case SET_VOICE_VOLUME: { 671 VoiceVolumeData *data = (VoiceVolumeData *)command->mParam.get(); 672 ALOGV("AudioCommandThread() processing set voice volume volume %f", 673 data->mVolume); 674 command->mStatus = AudioSystem::setVoiceVolume(data->mVolume); 675 }break; 676 case STOP_OUTPUT: { 677 StopOutputData *data = (StopOutputData *)command->mParam.get(); 678 ALOGV("AudioCommandThread() processing stop output %d", 679 data->mIO); 680 svc = mService.promote(); 681 if (svc == 0) { 682 break; 683 } 684 mLock.unlock(); 685 svc->doStopOutput(data->mIO, data->mStream, data->mSession); 686 mLock.lock(); 687 }break; 688 case RELEASE_OUTPUT: { 689 ReleaseOutputData *data = (ReleaseOutputData *)command->mParam.get(); 690 ALOGV("AudioCommandThread() processing release output %d", 691 data->mIO); 692 svc = mService.promote(); 693 if (svc == 0) { 694 break; 695 } 696 mLock.unlock(); 697 svc->doReleaseOutput(data->mIO, data->mStream, data->mSession); 698 mLock.lock(); 699 }break; 700 case CREATE_AUDIO_PATCH: { 701 CreateAudioPatchData *data = (CreateAudioPatchData *)command->mParam.get(); 702 ALOGV("AudioCommandThread() processing create audio patch"); 703 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 704 if (af == 0) { 705 command->mStatus = PERMISSION_DENIED; 706 } else { 707 command->mStatus = af->createAudioPatch(&data->mPatch, &data->mHandle); 708 } 709 } break; 710 case RELEASE_AUDIO_PATCH: { 711 ReleaseAudioPatchData *data = (ReleaseAudioPatchData *)command->mParam.get(); 712 ALOGV("AudioCommandThread() processing release audio patch"); 713 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 714 if (af == 0) { 715 command->mStatus = PERMISSION_DENIED; 716 } else { 717 command->mStatus = af->releaseAudioPatch(data->mHandle); 718 } 719 } break; 720 case UPDATE_AUDIOPORT_LIST: { 721 ALOGV("AudioCommandThread() processing update audio port list"); 722 svc = mService.promote(); 723 if (svc == 0) { 724 break; 725 } 726 mLock.unlock(); 727 svc->doOnAudioPortListUpdate(); 728 mLock.lock(); 729 }break; 730 case UPDATE_AUDIOPATCH_LIST: { 731 ALOGV("AudioCommandThread() processing update audio patch list"); 732 svc = mService.promote(); 733 if (svc == 0) { 734 break; 735 } 736 mLock.unlock(); 737 svc->doOnAudioPatchListUpdate(); 738 mLock.lock(); 739 }break; 740 case SET_AUDIOPORT_CONFIG: { 741 SetAudioPortConfigData *data = (SetAudioPortConfigData *)command->mParam.get(); 742 ALOGV("AudioCommandThread() processing set port config"); 743 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 744 if (af == 0) { 745 command->mStatus = PERMISSION_DENIED; 746 } else { 747 command->mStatus = af->setAudioPortConfig(&data->mConfig); 748 } 749 } break; 750 case DYN_POLICY_MIX_STATE_UPDATE: { 751 DynPolicyMixStateUpdateData *data = 752 (DynPolicyMixStateUpdateData *)command->mParam.get(); 753 ALOGV("AudioCommandThread() processing dyn policy mix state update %s %d", 754 data->mRegId.string(), data->mState); 755 svc = mService.promote(); 756 if (svc == 0) { 757 break; 758 } 759 mLock.unlock(); 760 svc->doOnDynamicPolicyMixStateUpdate(data->mRegId, data->mState); 761 mLock.lock(); 762 } break; 763 case RECORDING_CONFIGURATION_UPDATE: { 764 RecordingConfigurationUpdateData *data = 765 (RecordingConfigurationUpdateData *)command->mParam.get(); 766 ALOGV("AudioCommandThread() processing recording configuration update"); 767 svc = mService.promote(); 768 if (svc == 0) { 769 break; 770 } 771 mLock.unlock(); 772 svc->doOnRecordingConfigurationUpdate(data->mEvent, &data->mClientInfo, 773 &data->mClientConfig, &data->mDeviceConfig, 774 data->mPatchHandle); 775 mLock.lock(); 776 } break; 777 default: 778 ALOGW("AudioCommandThread() unknown command %d", command->mCommand); 779 } 780 { 781 Mutex::Autolock _l(command->mLock); 782 if (command->mWaitStatus) { 783 command->mWaitStatus = false; 784 command->mCond.signal(); 785 } 786 } 787 waitTime = -1; 788 // release mLock before releasing strong reference on the service as 789 // AudioPolicyService destructor calls AudioCommandThread::exit() which 790 // acquires mLock. 791 mLock.unlock(); 792 svc.clear(); 793 mLock.lock(); 794 } else { 795 waitTime = mAudioCommands[0]->mTime - curTime; 796 break; 797 } 798 } 799 800 // release delayed commands wake lock if the queue is empty 801 if (mAudioCommands.isEmpty()) { 802 release_wake_lock(mName.string()); 803 } 804 805 // At this stage we have either an empty command queue or the first command in the queue 806 // has a finite delay. So unless we are exiting it is safe to wait. 807 if (!exitPending()) { 808 ALOGV("AudioCommandThread() going to sleep"); 809 if (waitTime == -1) { 810 mWaitWorkCV.wait(mLock); 811 } else { 812 mWaitWorkCV.waitRelative(mLock, waitTime); 813 } 814 } 815 } 816 // release delayed commands wake lock before quitting 817 if (!mAudioCommands.isEmpty()) { 818 release_wake_lock(mName.string()); 819 } 820 mLock.unlock(); 821 return false; 822} 823 824status_t AudioPolicyService::AudioCommandThread::dump(int fd) 825{ 826 const size_t SIZE = 256; 827 char buffer[SIZE]; 828 String8 result; 829 830 snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this); 831 result.append(buffer); 832 write(fd, result.string(), result.size()); 833 834 bool locked = tryLock(mLock); 835 if (!locked) { 836 String8 result2(kCmdDeadlockedString); 837 write(fd, result2.string(), result2.size()); 838 } 839 840 snprintf(buffer, SIZE, "- Commands:\n"); 841 result = String8(buffer); 842 result.append(" Command Time Wait pParam\n"); 843 for (size_t i = 0; i < mAudioCommands.size(); i++) { 844 mAudioCommands[i]->dump(buffer, SIZE); 845 result.append(buffer); 846 } 847 result.append(" Last Command\n"); 848 if (mLastCommand != 0) { 849 mLastCommand->dump(buffer, SIZE); 850 result.append(buffer); 851 } else { 852 result.append(" none\n"); 853 } 854 855 write(fd, result.string(), result.size()); 856 857 if (locked) mLock.unlock(); 858 859 return NO_ERROR; 860} 861 862void AudioPolicyService::AudioCommandThread::startToneCommand(ToneGenerator::tone_type type, 863 audio_stream_type_t stream) 864{ 865 sp<AudioCommand> command = new AudioCommand(); 866 command->mCommand = START_TONE; 867 sp<ToneData> data = new ToneData(); 868 data->mType = type; 869 data->mStream = stream; 870 command->mParam = data; 871 ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream); 872 sendCommand(command); 873} 874 875void AudioPolicyService::AudioCommandThread::stopToneCommand() 876{ 877 sp<AudioCommand> command = new AudioCommand(); 878 command->mCommand = STOP_TONE; 879 ALOGV("AudioCommandThread() adding tone stop"); 880 sendCommand(command); 881} 882 883status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream, 884 float volume, 885 audio_io_handle_t output, 886 int delayMs) 887{ 888 sp<AudioCommand> command = new AudioCommand(); 889 command->mCommand = SET_VOLUME; 890 sp<VolumeData> data = new VolumeData(); 891 data->mStream = stream; 892 data->mVolume = volume; 893 data->mIO = output; 894 command->mParam = data; 895 command->mWaitStatus = true; 896 ALOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", 897 stream, volume, output); 898 return sendCommand(command, delayMs); 899} 900 901status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_handle_t ioHandle, 902 const char *keyValuePairs, 903 int delayMs) 904{ 905 sp<AudioCommand> command = new AudioCommand(); 906 command->mCommand = SET_PARAMETERS; 907 sp<ParametersData> data = new ParametersData(); 908 data->mIO = ioHandle; 909 data->mKeyValuePairs = String8(keyValuePairs); 910 command->mParam = data; 911 command->mWaitStatus = true; 912 ALOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", 913 keyValuePairs, ioHandle, delayMs); 914 return sendCommand(command, delayMs); 915} 916 917status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs) 918{ 919 sp<AudioCommand> command = new AudioCommand(); 920 command->mCommand = SET_VOICE_VOLUME; 921 sp<VoiceVolumeData> data = new VoiceVolumeData(); 922 data->mVolume = volume; 923 command->mParam = data; 924 command->mWaitStatus = true; 925 ALOGV("AudioCommandThread() adding set voice volume volume %f", volume); 926 return sendCommand(command, delayMs); 927} 928 929void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t output, 930 audio_stream_type_t stream, 931 audio_session_t session) 932{ 933 sp<AudioCommand> command = new AudioCommand(); 934 command->mCommand = STOP_OUTPUT; 935 sp<StopOutputData> data = new StopOutputData(); 936 data->mIO = output; 937 data->mStream = stream; 938 data->mSession = session; 939 command->mParam = data; 940 ALOGV("AudioCommandThread() adding stop output %d", output); 941 sendCommand(command); 942} 943 944void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output, 945 audio_stream_type_t stream, 946 audio_session_t session) 947{ 948 sp<AudioCommand> command = new AudioCommand(); 949 command->mCommand = RELEASE_OUTPUT; 950 sp<ReleaseOutputData> data = new ReleaseOutputData(); 951 data->mIO = output; 952 data->mStream = stream; 953 data->mSession = session; 954 command->mParam = data; 955 ALOGV("AudioCommandThread() adding release output %d", output); 956 sendCommand(command); 957} 958 959status_t AudioPolicyService::AudioCommandThread::createAudioPatchCommand( 960 const struct audio_patch *patch, 961 audio_patch_handle_t *handle, 962 int delayMs) 963{ 964 status_t status = NO_ERROR; 965 966 sp<AudioCommand> command = new AudioCommand(); 967 command->mCommand = CREATE_AUDIO_PATCH; 968 CreateAudioPatchData *data = new CreateAudioPatchData(); 969 data->mPatch = *patch; 970 data->mHandle = *handle; 971 command->mParam = data; 972 command->mWaitStatus = true; 973 ALOGV("AudioCommandThread() adding create patch delay %d", delayMs); 974 status = sendCommand(command, delayMs); 975 if (status == NO_ERROR) { 976 *handle = data->mHandle; 977 } 978 return status; 979} 980 981status_t AudioPolicyService::AudioCommandThread::releaseAudioPatchCommand(audio_patch_handle_t handle, 982 int delayMs) 983{ 984 sp<AudioCommand> command = new AudioCommand(); 985 command->mCommand = RELEASE_AUDIO_PATCH; 986 ReleaseAudioPatchData *data = new ReleaseAudioPatchData(); 987 data->mHandle = handle; 988 command->mParam = data; 989 command->mWaitStatus = true; 990 ALOGV("AudioCommandThread() adding release patch delay %d", delayMs); 991 return sendCommand(command, delayMs); 992} 993 994void AudioPolicyService::AudioCommandThread::updateAudioPortListCommand() 995{ 996 sp<AudioCommand> command = new AudioCommand(); 997 command->mCommand = UPDATE_AUDIOPORT_LIST; 998 ALOGV("AudioCommandThread() adding update audio port list"); 999 sendCommand(command); 1000} 1001 1002void AudioPolicyService::AudioCommandThread::updateAudioPatchListCommand() 1003{ 1004 sp<AudioCommand>command = new AudioCommand(); 1005 command->mCommand = UPDATE_AUDIOPATCH_LIST; 1006 ALOGV("AudioCommandThread() adding update audio patch list"); 1007 sendCommand(command); 1008} 1009 1010status_t AudioPolicyService::AudioCommandThread::setAudioPortConfigCommand( 1011 const struct audio_port_config *config, int delayMs) 1012{ 1013 sp<AudioCommand> command = new AudioCommand(); 1014 command->mCommand = SET_AUDIOPORT_CONFIG; 1015 SetAudioPortConfigData *data = new SetAudioPortConfigData(); 1016 data->mConfig = *config; 1017 command->mParam = data; 1018 command->mWaitStatus = true; 1019 ALOGV("AudioCommandThread() adding set port config delay %d", delayMs); 1020 return sendCommand(command, delayMs); 1021} 1022 1023void AudioPolicyService::AudioCommandThread::dynamicPolicyMixStateUpdateCommand( 1024 const String8& regId, int32_t state) 1025{ 1026 sp<AudioCommand> command = new AudioCommand(); 1027 command->mCommand = DYN_POLICY_MIX_STATE_UPDATE; 1028 DynPolicyMixStateUpdateData *data = new DynPolicyMixStateUpdateData(); 1029 data->mRegId = regId; 1030 data->mState = state; 1031 command->mParam = data; 1032 ALOGV("AudioCommandThread() sending dynamic policy mix (id=%s) state update to %d", 1033 regId.string(), state); 1034 sendCommand(command); 1035} 1036 1037void AudioPolicyService::AudioCommandThread::recordingConfigurationUpdateCommand( 1038 int event, const record_client_info_t *clientInfo, 1039 const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig, 1040 audio_patch_handle_t patchHandle) 1041{ 1042 sp<AudioCommand>command = new AudioCommand(); 1043 command->mCommand = RECORDING_CONFIGURATION_UPDATE; 1044 RecordingConfigurationUpdateData *data = new RecordingConfigurationUpdateData(); 1045 data->mEvent = event; 1046 data->mClientInfo = *clientInfo; 1047 data->mClientConfig = *clientConfig; 1048 data->mDeviceConfig = *deviceConfig; 1049 data->mPatchHandle = patchHandle; 1050 command->mParam = data; 1051 ALOGV("AudioCommandThread() adding recording configuration update event %d, source %d uid %u", 1052 event, clientInfo->source, clientInfo->uid); 1053 sendCommand(command); 1054} 1055 1056status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs) 1057{ 1058 { 1059 Mutex::Autolock _l(mLock); 1060 insertCommand_l(command, delayMs); 1061 mWaitWorkCV.signal(); 1062 } 1063 Mutex::Autolock _l(command->mLock); 1064 while (command->mWaitStatus) { 1065 nsecs_t timeOutNs = kAudioCommandTimeoutNs + milliseconds(delayMs); 1066 if (command->mCond.waitRelative(command->mLock, timeOutNs) != NO_ERROR) { 1067 command->mStatus = TIMED_OUT; 1068 command->mWaitStatus = false; 1069 } 1070 } 1071 return command->mStatus; 1072} 1073 1074// insertCommand_l() must be called with mLock held 1075void AudioPolicyService::AudioCommandThread::insertCommand_l(sp<AudioCommand>& command, int delayMs) 1076{ 1077 ssize_t i; // not size_t because i will count down to -1 1078 Vector < sp<AudioCommand> > removedCommands; 1079 command->mTime = systemTime() + milliseconds(delayMs); 1080 1081 // acquire wake lock to make sure delayed commands are processed 1082 if (mAudioCommands.isEmpty()) { 1083 acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string()); 1084 } 1085 1086 // check same pending commands with later time stamps and eliminate them 1087 for (i = (ssize_t)mAudioCommands.size()-1; i >= 0; i--) { 1088 sp<AudioCommand> command2 = mAudioCommands[i]; 1089 // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands 1090 if (command2->mTime <= command->mTime) break; 1091 1092 // create audio patch or release audio patch commands are equivalent 1093 // with regard to filtering 1094 if ((command->mCommand == CREATE_AUDIO_PATCH) || 1095 (command->mCommand == RELEASE_AUDIO_PATCH)) { 1096 if ((command2->mCommand != CREATE_AUDIO_PATCH) && 1097 (command2->mCommand != RELEASE_AUDIO_PATCH)) { 1098 continue; 1099 } 1100 } else if (command2->mCommand != command->mCommand) continue; 1101 1102 switch (command->mCommand) { 1103 case SET_PARAMETERS: { 1104 ParametersData *data = (ParametersData *)command->mParam.get(); 1105 ParametersData *data2 = (ParametersData *)command2->mParam.get(); 1106 if (data->mIO != data2->mIO) break; 1107 ALOGV("Comparing parameter command %s to new command %s", 1108 data2->mKeyValuePairs.string(), data->mKeyValuePairs.string()); 1109 AudioParameter param = AudioParameter(data->mKeyValuePairs); 1110 AudioParameter param2 = AudioParameter(data2->mKeyValuePairs); 1111 for (size_t j = 0; j < param.size(); j++) { 1112 String8 key; 1113 String8 value; 1114 param.getAt(j, key, value); 1115 for (size_t k = 0; k < param2.size(); k++) { 1116 String8 key2; 1117 String8 value2; 1118 param2.getAt(k, key2, value2); 1119 if (key2 == key) { 1120 param2.remove(key2); 1121 ALOGV("Filtering out parameter %s", key2.string()); 1122 break; 1123 } 1124 } 1125 } 1126 // if all keys have been filtered out, remove the command. 1127 // otherwise, update the key value pairs 1128 if (param2.size() == 0) { 1129 removedCommands.add(command2); 1130 } else { 1131 data2->mKeyValuePairs = param2.toString(); 1132 } 1133 command->mTime = command2->mTime; 1134 // force delayMs to non 0 so that code below does not request to wait for 1135 // command status as the command is now delayed 1136 delayMs = 1; 1137 } break; 1138 1139 case SET_VOLUME: { 1140 VolumeData *data = (VolumeData *)command->mParam.get(); 1141 VolumeData *data2 = (VolumeData *)command2->mParam.get(); 1142 if (data->mIO != data2->mIO) break; 1143 if (data->mStream != data2->mStream) break; 1144 ALOGV("Filtering out volume command on output %d for stream %d", 1145 data->mIO, data->mStream); 1146 removedCommands.add(command2); 1147 command->mTime = command2->mTime; 1148 // force delayMs to non 0 so that code below does not request to wait for 1149 // command status as the command is now delayed 1150 delayMs = 1; 1151 } break; 1152 1153 case SET_VOICE_VOLUME: { 1154 VoiceVolumeData *data = (VoiceVolumeData *)command->mParam.get(); 1155 VoiceVolumeData *data2 = (VoiceVolumeData *)command2->mParam.get(); 1156 ALOGV("Filtering out voice volume command value %f replaced by %f", 1157 data2->mVolume, data->mVolume); 1158 removedCommands.add(command2); 1159 command->mTime = command2->mTime; 1160 // force delayMs to non 0 so that code below does not request to wait for 1161 // command status as the command is now delayed 1162 delayMs = 1; 1163 } break; 1164 1165 case CREATE_AUDIO_PATCH: 1166 case RELEASE_AUDIO_PATCH: { 1167 audio_patch_handle_t handle; 1168 struct audio_patch patch; 1169 if (command->mCommand == CREATE_AUDIO_PATCH) { 1170 handle = ((CreateAudioPatchData *)command->mParam.get())->mHandle; 1171 patch = ((CreateAudioPatchData *)command->mParam.get())->mPatch; 1172 } else { 1173 handle = ((ReleaseAudioPatchData *)command->mParam.get())->mHandle; 1174 } 1175 audio_patch_handle_t handle2; 1176 struct audio_patch patch2; 1177 if (command2->mCommand == CREATE_AUDIO_PATCH) { 1178 handle2 = ((CreateAudioPatchData *)command2->mParam.get())->mHandle; 1179 patch2 = ((CreateAudioPatchData *)command2->mParam.get())->mPatch; 1180 } else { 1181 handle2 = ((ReleaseAudioPatchData *)command2->mParam.get())->mHandle; 1182 memset(&patch2, 0, sizeof(patch2)); 1183 } 1184 if (handle != handle2) break; 1185 /* Filter CREATE_AUDIO_PATCH commands only when they are issued for 1186 same output. */ 1187 if( (command->mCommand == CREATE_AUDIO_PATCH) && 1188 (command2->mCommand == CREATE_AUDIO_PATCH) ) { 1189 bool isOutputDiff = false; 1190 if (patch.num_sources == patch2.num_sources) { 1191 for (unsigned count = 0; count < patch.num_sources; count++) { 1192 if (patch.sources[count].id != patch2.sources[count].id) { 1193 isOutputDiff = true; 1194 break; 1195 } 1196 } 1197 if (isOutputDiff) 1198 break; 1199 } 1200 } 1201 ALOGV("Filtering out %s audio patch command for handle %d", 1202 (command->mCommand == CREATE_AUDIO_PATCH) ? "create" : "release", handle); 1203 removedCommands.add(command2); 1204 command->mTime = command2->mTime; 1205 // force delayMs to non 0 so that code below does not request to wait for 1206 // command status as the command is now delayed 1207 delayMs = 1; 1208 } break; 1209 1210 case DYN_POLICY_MIX_STATE_UPDATE: { 1211 1212 } break; 1213 1214 case RECORDING_CONFIGURATION_UPDATE: { 1215 1216 } break; 1217 1218 case START_TONE: 1219 case STOP_TONE: 1220 default: 1221 break; 1222 } 1223 } 1224 1225 // remove filtered commands 1226 for (size_t j = 0; j < removedCommands.size(); j++) { 1227 // removed commands always have time stamps greater than current command 1228 for (size_t k = i + 1; k < mAudioCommands.size(); k++) { 1229 if (mAudioCommands[k].get() == removedCommands[j].get()) { 1230 ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand); 1231 mAudioCommands.removeAt(k); 1232 break; 1233 } 1234 } 1235 } 1236 removedCommands.clear(); 1237 1238 // Disable wait for status if delay is not 0. 1239 // Except for create audio patch command because the returned patch handle 1240 // is needed by audio policy manager 1241 if (delayMs != 0 && command->mCommand != CREATE_AUDIO_PATCH) { 1242 command->mWaitStatus = false; 1243 } 1244 1245 // insert command at the right place according to its time stamp 1246 ALOGV("inserting command: %d at index %zd, num commands %zu", 1247 command->mCommand, i+1, mAudioCommands.size()); 1248 mAudioCommands.insertAt(command, i + 1); 1249} 1250 1251void AudioPolicyService::AudioCommandThread::exit() 1252{ 1253 ALOGV("AudioCommandThread::exit"); 1254 { 1255 AutoMutex _l(mLock); 1256 requestExit(); 1257 mWaitWorkCV.signal(); 1258 } 1259 // Note that we can call it from the thread loop if all other references have been released 1260 // but it will safely return WOULD_BLOCK in this case 1261 requestExitAndWait(); 1262} 1263 1264void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size) 1265{ 1266 snprintf(buffer, size, " %02d %06d.%03d %01u %p\n", 1267 mCommand, 1268 (int)ns2s(mTime), 1269 (int)ns2ms(mTime)%1000, 1270 mWaitStatus, 1271 mParam.get()); 1272} 1273 1274/******* helpers for the service_ops callbacks defined below *********/ 1275void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, 1276 const char *keyValuePairs, 1277 int delayMs) 1278{ 1279 mAudioCommandThread->parametersCommand(ioHandle, keyValuePairs, 1280 delayMs); 1281} 1282 1283int AudioPolicyService::setStreamVolume(audio_stream_type_t stream, 1284 float volume, 1285 audio_io_handle_t output, 1286 int delayMs) 1287{ 1288 return (int)mAudioCommandThread->volumeCommand(stream, volume, 1289 output, delayMs); 1290} 1291 1292int AudioPolicyService::startTone(audio_policy_tone_t tone, 1293 audio_stream_type_t stream) 1294{ 1295 if (tone != AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION) { 1296 ALOGE("startTone: illegal tone requested (%d)", tone); 1297 } 1298 if (stream != AUDIO_STREAM_VOICE_CALL) { 1299 ALOGE("startTone: illegal stream (%d) requested for tone %d", stream, 1300 tone); 1301 } 1302 mTonePlaybackThread->startToneCommand(ToneGenerator::TONE_SUP_CALL_WAITING, 1303 AUDIO_STREAM_VOICE_CALL); 1304 return 0; 1305} 1306 1307int AudioPolicyService::stopTone() 1308{ 1309 mTonePlaybackThread->stopToneCommand(); 1310 return 0; 1311} 1312 1313int AudioPolicyService::setVoiceVolume(float volume, int delayMs) 1314{ 1315 return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs); 1316} 1317 1318extern "C" { 1319audio_module_handle_t aps_load_hw_module(void *service __unused, 1320 const char *name); 1321audio_io_handle_t aps_open_output(void *service __unused, 1322 audio_devices_t *pDevices, 1323 uint32_t *pSamplingRate, 1324 audio_format_t *pFormat, 1325 audio_channel_mask_t *pChannelMask, 1326 uint32_t *pLatencyMs, 1327 audio_output_flags_t flags); 1328 1329audio_io_handle_t aps_open_output_on_module(void *service __unused, 1330 audio_module_handle_t module, 1331 audio_devices_t *pDevices, 1332 uint32_t *pSamplingRate, 1333 audio_format_t *pFormat, 1334 audio_channel_mask_t *pChannelMask, 1335 uint32_t *pLatencyMs, 1336 audio_output_flags_t flags, 1337 const audio_offload_info_t *offloadInfo); 1338audio_io_handle_t aps_open_dup_output(void *service __unused, 1339 audio_io_handle_t output1, 1340 audio_io_handle_t output2); 1341int aps_close_output(void *service __unused, audio_io_handle_t output); 1342int aps_suspend_output(void *service __unused, audio_io_handle_t output); 1343int aps_restore_output(void *service __unused, audio_io_handle_t output); 1344audio_io_handle_t aps_open_input(void *service __unused, 1345 audio_devices_t *pDevices, 1346 uint32_t *pSamplingRate, 1347 audio_format_t *pFormat, 1348 audio_channel_mask_t *pChannelMask, 1349 audio_in_acoustics_t acoustics __unused); 1350audio_io_handle_t aps_open_input_on_module(void *service __unused, 1351 audio_module_handle_t module, 1352 audio_devices_t *pDevices, 1353 uint32_t *pSamplingRate, 1354 audio_format_t *pFormat, 1355 audio_channel_mask_t *pChannelMask); 1356int aps_close_input(void *service __unused, audio_io_handle_t input); 1357int aps_invalidate_stream(void *service __unused, audio_stream_type_t stream); 1358int aps_move_effects(void *service __unused, audio_session_t session, 1359 audio_io_handle_t src_output, 1360 audio_io_handle_t dst_output); 1361char * aps_get_parameters(void *service __unused, audio_io_handle_t io_handle, 1362 const char *keys); 1363void aps_set_parameters(void *service, audio_io_handle_t io_handle, 1364 const char *kv_pairs, int delay_ms); 1365int aps_set_stream_volume(void *service, audio_stream_type_t stream, 1366 float volume, audio_io_handle_t output, 1367 int delay_ms); 1368int aps_start_tone(void *service, audio_policy_tone_t tone, 1369 audio_stream_type_t stream); 1370int aps_stop_tone(void *service); 1371int aps_set_voice_volume(void *service, float volume, int delay_ms); 1372}; 1373 1374} // namespace android 1375