AudioPolicyInterfaceImpl.cpp revision 3994ffdd2c280aa5fad9f3c41255371cd545c7cf
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 "AudioPolicyIntefaceImpl" 18//#define LOG_NDEBUG 0 19 20#include <utils/Log.h> 21#include "AudioPolicyService.h" 22#include "ServiceUtilities.h" 23 24namespace android { 25 26 27// ---------------------------------------------------------------------------- 28 29status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device, 30 audio_policy_dev_state_t state, 31 const char *device_address, 32 const char *device_name) 33{ 34 if (mAudioPolicyManager == NULL) { 35 return NO_INIT; 36 } 37 if (!settingsAllowed()) { 38 return PERMISSION_DENIED; 39 } 40 if (!audio_is_output_device(device) && !audio_is_input_device(device)) { 41 return BAD_VALUE; 42 } 43 if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE && 44 state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) { 45 return BAD_VALUE; 46 } 47 48 ALOGV("setDeviceConnectionState()"); 49 Mutex::Autolock _l(mLock); 50 return mAudioPolicyManager->setDeviceConnectionState(device, state, 51 device_address, device_name); 52} 53 54audio_policy_dev_state_t AudioPolicyService::getDeviceConnectionState( 55 audio_devices_t device, 56 const char *device_address) 57{ 58 if (mAudioPolicyManager == NULL) { 59 return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; 60 } 61 return mAudioPolicyManager->getDeviceConnectionState(device, 62 device_address); 63} 64 65status_t AudioPolicyService::setPhoneState(audio_mode_t state) 66{ 67 if (mAudioPolicyManager == NULL) { 68 return NO_INIT; 69 } 70 if (!settingsAllowed()) { 71 return PERMISSION_DENIED; 72 } 73 if (uint32_t(state) >= AUDIO_MODE_CNT) { 74 return BAD_VALUE; 75 } 76 77 ALOGV("setPhoneState()"); 78 79 // acquire lock before calling setMode() so that setMode() + setPhoneState() are an atomic 80 // operation from policy manager standpoint (no other operation (e.g track start or stop) 81 // can be interleaved). 82 Mutex::Autolock _l(mLock); 83 84 // TODO: check if it is more appropriate to do it in platform specific policy manager 85 AudioSystem::setMode(state); 86 87 mAudioPolicyManager->setPhoneState(state); 88 mPhoneState = state; 89 return NO_ERROR; 90} 91 92audio_mode_t AudioPolicyService::getPhoneState() 93{ 94 Mutex::Autolock _l(mLock); 95 return mPhoneState; 96} 97 98status_t AudioPolicyService::setForceUse(audio_policy_force_use_t usage, 99 audio_policy_forced_cfg_t config) 100{ 101 if (mAudioPolicyManager == NULL) { 102 return NO_INIT; 103 } 104 if (!settingsAllowed()) { 105 return PERMISSION_DENIED; 106 } 107 if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) { 108 return BAD_VALUE; 109 } 110 if (config < 0 || config >= AUDIO_POLICY_FORCE_CFG_CNT) { 111 return BAD_VALUE; 112 } 113 ALOGV("setForceUse()"); 114 Mutex::Autolock _l(mLock); 115 mAudioPolicyManager->setForceUse(usage, config); 116 return NO_ERROR; 117} 118 119audio_policy_forced_cfg_t AudioPolicyService::getForceUse(audio_policy_force_use_t usage) 120{ 121 if (mAudioPolicyManager == NULL) { 122 return AUDIO_POLICY_FORCE_NONE; 123 } 124 if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) { 125 return AUDIO_POLICY_FORCE_NONE; 126 } 127 return mAudioPolicyManager->getForceUse(usage); 128} 129 130audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream, 131 uint32_t samplingRate, 132 audio_format_t format, 133 audio_channel_mask_t channelMask, 134 audio_output_flags_t flags, 135 const audio_offload_info_t *offloadInfo) 136{ 137 if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { 138 return AUDIO_IO_HANDLE_NONE; 139 } 140 if (mAudioPolicyManager == NULL) { 141 return AUDIO_IO_HANDLE_NONE; 142 } 143 ALOGV("getOutput()"); 144 Mutex::Autolock _l(mLock); 145 return mAudioPolicyManager->getOutput(stream, samplingRate, 146 format, channelMask, flags, offloadInfo); 147} 148 149status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr, 150 audio_io_handle_t *output, 151 audio_session_t session, 152 audio_stream_type_t *stream, 153 uid_t uid, 154 uint32_t samplingRate, 155 audio_format_t format, 156 audio_channel_mask_t channelMask, 157 audio_output_flags_t flags, 158 audio_port_handle_t selectedDeviceId, 159 const audio_offload_info_t *offloadInfo) 160{ 161 if (mAudioPolicyManager == NULL) { 162 return NO_INIT; 163 } 164 ALOGV("getOutput()"); 165 Mutex::Autolock _l(mLock); 166 167 // if the caller is us, trust the specified uid 168 if (IPCThreadState::self()->getCallingPid() != getpid_cached || uid == (uid_t)-1) { 169 uid_t newclientUid = IPCThreadState::self()->getCallingUid(); 170 if (uid != (uid_t)-1 && uid != newclientUid) { 171 ALOGW("%s uid %d tried to pass itself off as %d", __FUNCTION__, newclientUid, uid); 172 } 173 uid = newclientUid; 174 } 175 return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, samplingRate, 176 format, channelMask, flags, selectedDeviceId, offloadInfo); 177} 178 179status_t AudioPolicyService::startOutput(audio_io_handle_t output, 180 audio_stream_type_t stream, 181 audio_session_t session) 182{ 183 if (uint32_t(stream) >= AUDIO_STREAM_CNT) { 184 return BAD_VALUE; 185 } 186 if (mAudioPolicyManager == NULL) { 187 return NO_INIT; 188 } 189 ALOGV("startOutput()"); 190 sp<AudioPolicyEffects>audioPolicyEffects; 191 { 192 Mutex::Autolock _l(mLock); 193 audioPolicyEffects = mAudioPolicyEffects; 194 } 195 if (audioPolicyEffects != 0) { 196 // create audio processors according to stream 197 status_t status = audioPolicyEffects->addOutputSessionEffects(output, stream, session); 198 if (status != NO_ERROR && status != ALREADY_EXISTS) { 199 ALOGW("Failed to add effects on session %d", session); 200 } 201 } 202 Mutex::Autolock _l(mLock); 203 return mAudioPolicyManager->startOutput(output, stream, session); 204} 205 206status_t AudioPolicyService::stopOutput(audio_io_handle_t output, 207 audio_stream_type_t stream, 208 audio_session_t session) 209{ 210 if (uint32_t(stream) >= AUDIO_STREAM_CNT) { 211 return BAD_VALUE; 212 } 213 if (mAudioPolicyManager == NULL) { 214 return NO_INIT; 215 } 216 ALOGV("stopOutput()"); 217 mOutputCommandThread->stopOutputCommand(output, stream, session); 218 return NO_ERROR; 219} 220 221status_t AudioPolicyService::doStopOutput(audio_io_handle_t output, 222 audio_stream_type_t stream, 223 audio_session_t session) 224{ 225 ALOGV("doStopOutput from tid %d", gettid()); 226 sp<AudioPolicyEffects>audioPolicyEffects; 227 { 228 Mutex::Autolock _l(mLock); 229 audioPolicyEffects = mAudioPolicyEffects; 230 } 231 if (audioPolicyEffects != 0) { 232 // release audio processors from the stream 233 status_t status = audioPolicyEffects->releaseOutputSessionEffects(output, stream, session); 234 if (status != NO_ERROR && status != ALREADY_EXISTS) { 235 ALOGW("Failed to release effects on session %d", session); 236 } 237 } 238 Mutex::Autolock _l(mLock); 239 return mAudioPolicyManager->stopOutput(output, stream, session); 240} 241 242void AudioPolicyService::releaseOutput(audio_io_handle_t output, 243 audio_stream_type_t stream, 244 audio_session_t session) 245{ 246 if (mAudioPolicyManager == NULL) { 247 return; 248 } 249 ALOGV("releaseOutput()"); 250 mOutputCommandThread->releaseOutputCommand(output, stream, session); 251} 252 253void AudioPolicyService::doReleaseOutput(audio_io_handle_t output, 254 audio_stream_type_t stream, 255 audio_session_t session) 256{ 257 ALOGV("doReleaseOutput from tid %d", gettid()); 258 Mutex::Autolock _l(mLock); 259 mAudioPolicyManager->releaseOutput(output, stream, session); 260} 261 262status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr, 263 audio_io_handle_t *input, 264 audio_session_t session, 265 uid_t uid, 266 uint32_t samplingRate, 267 audio_format_t format, 268 audio_channel_mask_t channelMask, 269 audio_input_flags_t flags, 270 audio_port_handle_t selectedDeviceId) 271{ 272 if (mAudioPolicyManager == NULL) { 273 return NO_INIT; 274 } 275 // already checked by client, but double-check in case the client wrapper is bypassed 276 if (attr->source >= AUDIO_SOURCE_CNT && attr->source != AUDIO_SOURCE_HOTWORD && 277 attr->source != AUDIO_SOURCE_FM_TUNER) { 278 return BAD_VALUE; 279 } 280 281 if ((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) { 282 return BAD_VALUE; 283 } 284 sp<AudioPolicyEffects>audioPolicyEffects; 285 status_t status; 286 AudioPolicyInterface::input_type_t inputType; 287 // if the caller is us, trust the specified uid 288 if (IPCThreadState::self()->getCallingPid() != getpid_cached || uid == (uid_t)-1) { 289 uid_t newclientUid = IPCThreadState::self()->getCallingUid(); 290 if (uid != (uid_t)-1 && uid != newclientUid) { 291 ALOGW("%s uid %d tried to pass itself off as %d", __FUNCTION__, newclientUid, uid); 292 } 293 uid = newclientUid; 294 } 295 296 { 297 Mutex::Autolock _l(mLock); 298 // the audio_in_acoustics_t parameter is ignored by get_input() 299 status = mAudioPolicyManager->getInputForAttr(attr, input, session, uid, 300 samplingRate, format, channelMask, 301 flags, selectedDeviceId, 302 &inputType); 303 audioPolicyEffects = mAudioPolicyEffects; 304 305 if (status == NO_ERROR) { 306 // enforce permission (if any) required for each type of input 307 switch (inputType) { 308 case AudioPolicyInterface::API_INPUT_LEGACY: 309 break; 310 case AudioPolicyInterface::API_INPUT_TELEPHONY_RX: 311 // FIXME: use the same permission as for remote submix for now. 312 case AudioPolicyInterface::API_INPUT_MIX_CAPTURE: 313 if (!captureAudioOutputAllowed()) { 314 ALOGE("getInputForAttr() permission denied: capture not allowed"); 315 status = PERMISSION_DENIED; 316 } 317 break; 318 case AudioPolicyInterface::API_INPUT_MIX_EXT_POLICY_REROUTE: 319 if (!modifyAudioRoutingAllowed()) { 320 ALOGE("getInputForAttr() permission denied: modify audio routing not allowed"); 321 status = PERMISSION_DENIED; 322 } 323 break; 324 case AudioPolicyInterface::API_INPUT_INVALID: 325 default: 326 LOG_ALWAYS_FATAL("getInputForAttr() encountered an invalid input type %d", 327 (int)inputType); 328 } 329 } 330 331 if (status != NO_ERROR) { 332 if (status == PERMISSION_DENIED) { 333 mAudioPolicyManager->releaseInput(*input, session); 334 } 335 return status; 336 } 337 } 338 339 if (audioPolicyEffects != 0) { 340 // create audio pre processors according to input source 341 status_t status = audioPolicyEffects->addInputEffects(*input, attr->source, session); 342 if (status != NO_ERROR && status != ALREADY_EXISTS) { 343 ALOGW("Failed to add effects on input %d", *input); 344 } 345 } 346 return NO_ERROR; 347} 348 349status_t AudioPolicyService::startInput(audio_io_handle_t input, 350 audio_session_t session) 351{ 352 if (mAudioPolicyManager == NULL) { 353 return NO_INIT; 354 } 355 Mutex::Autolock _l(mLock); 356 357 return mAudioPolicyManager->startInput(input, session); 358} 359 360status_t AudioPolicyService::stopInput(audio_io_handle_t input, 361 audio_session_t session) 362{ 363 if (mAudioPolicyManager == NULL) { 364 return NO_INIT; 365 } 366 Mutex::Autolock _l(mLock); 367 368 return mAudioPolicyManager->stopInput(input, session); 369} 370 371void AudioPolicyService::releaseInput(audio_io_handle_t input, 372 audio_session_t session) 373{ 374 if (mAudioPolicyManager == NULL) { 375 return; 376 } 377 sp<AudioPolicyEffects>audioPolicyEffects; 378 { 379 Mutex::Autolock _l(mLock); 380 mAudioPolicyManager->releaseInput(input, session); 381 audioPolicyEffects = mAudioPolicyEffects; 382 } 383 if (audioPolicyEffects != 0) { 384 // release audio processors from the input 385 status_t status = audioPolicyEffects->releaseInputEffects(input); 386 if(status != NO_ERROR) { 387 ALOGW("Failed to release effects on input %d", input); 388 } 389 } 390} 391 392status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream, 393 int indexMin, 394 int indexMax) 395{ 396 if (mAudioPolicyManager == NULL) { 397 return NO_INIT; 398 } 399 if (!settingsAllowed()) { 400 return PERMISSION_DENIED; 401 } 402 if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { 403 return BAD_VALUE; 404 } 405 Mutex::Autolock _l(mLock); 406 mAudioPolicyManager->initStreamVolume(stream, indexMin, indexMax); 407 return NO_ERROR; 408} 409 410status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream, 411 int index, 412 audio_devices_t device) 413{ 414 if (mAudioPolicyManager == NULL) { 415 return NO_INIT; 416 } 417 if (!settingsAllowed()) { 418 return PERMISSION_DENIED; 419 } 420 if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { 421 return BAD_VALUE; 422 } 423 Mutex::Autolock _l(mLock); 424 return mAudioPolicyManager->setStreamVolumeIndex(stream, 425 index, 426 device); 427} 428 429status_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream, 430 int *index, 431 audio_devices_t device) 432{ 433 if (mAudioPolicyManager == NULL) { 434 return NO_INIT; 435 } 436 if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { 437 return BAD_VALUE; 438 } 439 Mutex::Autolock _l(mLock); 440 return mAudioPolicyManager->getStreamVolumeIndex(stream, 441 index, 442 device); 443} 444 445uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream) 446{ 447 if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { 448 return 0; 449 } 450 if (mAudioPolicyManager == NULL) { 451 return 0; 452 } 453 return mAudioPolicyManager->getStrategyForStream(stream); 454} 455 456//audio policy: use audio_device_t appropriately 457 458audio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream) 459{ 460 if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { 461 return AUDIO_DEVICE_NONE; 462 } 463 if (mAudioPolicyManager == NULL) { 464 return AUDIO_DEVICE_NONE; 465 } 466 return mAudioPolicyManager->getDevicesForStream(stream); 467} 468 469audio_io_handle_t AudioPolicyService::getOutputForEffect(const effect_descriptor_t *desc) 470{ 471 // FIXME change return type to status_t, and return NO_INIT here 472 if (mAudioPolicyManager == NULL) { 473 return 0; 474 } 475 Mutex::Autolock _l(mLock); 476 return mAudioPolicyManager->getOutputForEffect(desc); 477} 478 479status_t AudioPolicyService::registerEffect(const effect_descriptor_t *desc, 480 audio_io_handle_t io, 481 uint32_t strategy, 482 int session, 483 int id) 484{ 485 if (mAudioPolicyManager == NULL) { 486 return NO_INIT; 487 } 488 return mAudioPolicyManager->registerEffect(desc, io, strategy, session, id); 489} 490 491status_t AudioPolicyService::unregisterEffect(int id) 492{ 493 if (mAudioPolicyManager == NULL) { 494 return NO_INIT; 495 } 496 return mAudioPolicyManager->unregisterEffect(id); 497} 498 499status_t AudioPolicyService::setEffectEnabled(int id, bool enabled) 500{ 501 if (mAudioPolicyManager == NULL) { 502 return NO_INIT; 503 } 504 return mAudioPolicyManager->setEffectEnabled(id, enabled); 505} 506 507bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const 508{ 509 if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { 510 return false; 511 } 512 if (mAudioPolicyManager == NULL) { 513 return false; 514 } 515 Mutex::Autolock _l(mLock); 516 return mAudioPolicyManager->isStreamActive(stream, inPastMs); 517} 518 519bool AudioPolicyService::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const 520{ 521 if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { 522 return false; 523 } 524 if (mAudioPolicyManager == NULL) { 525 return false; 526 } 527 Mutex::Autolock _l(mLock); 528 return mAudioPolicyManager->isStreamActiveRemotely(stream, inPastMs); 529} 530 531bool AudioPolicyService::isSourceActive(audio_source_t source) const 532{ 533 if (mAudioPolicyManager == NULL) { 534 return false; 535 } 536 Mutex::Autolock _l(mLock); 537 return mAudioPolicyManager->isSourceActive(source); 538} 539 540status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession, 541 effect_descriptor_t *descriptors, 542 uint32_t *count) 543{ 544 if (mAudioPolicyManager == NULL) { 545 *count = 0; 546 return NO_INIT; 547 } 548 sp<AudioPolicyEffects>audioPolicyEffects; 549 { 550 Mutex::Autolock _l(mLock); 551 audioPolicyEffects = mAudioPolicyEffects; 552 } 553 if (audioPolicyEffects == 0) { 554 *count = 0; 555 return NO_INIT; 556 } 557 return audioPolicyEffects->queryDefaultInputEffects(audioSession, descriptors, count); 558} 559 560bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info) 561{ 562 if (mAudioPolicyManager == NULL) { 563 ALOGV("mAudioPolicyManager == NULL"); 564 return false; 565 } 566 567 return mAudioPolicyManager->isOffloadSupported(info); 568} 569 570status_t AudioPolicyService::listAudioPorts(audio_port_role_t role, 571 audio_port_type_t type, 572 unsigned int *num_ports, 573 struct audio_port *ports, 574 unsigned int *generation) 575{ 576 Mutex::Autolock _l(mLock); 577 if (mAudioPolicyManager == NULL) { 578 return NO_INIT; 579 } 580 581 return mAudioPolicyManager->listAudioPorts(role, type, num_ports, ports, generation); 582} 583 584status_t AudioPolicyService::getAudioPort(struct audio_port *port) 585{ 586 Mutex::Autolock _l(mLock); 587 if (mAudioPolicyManager == NULL) { 588 return NO_INIT; 589 } 590 591 return mAudioPolicyManager->getAudioPort(port); 592} 593 594status_t AudioPolicyService::createAudioPatch(const struct audio_patch *patch, 595 audio_patch_handle_t *handle) 596{ 597 Mutex::Autolock _l(mLock); 598 if(!modifyAudioRoutingAllowed()) { 599 return PERMISSION_DENIED; 600 } 601 if (mAudioPolicyManager == NULL) { 602 return NO_INIT; 603 } 604 return mAudioPolicyManager->createAudioPatch(patch, handle, 605 IPCThreadState::self()->getCallingUid()); 606} 607 608status_t AudioPolicyService::releaseAudioPatch(audio_patch_handle_t handle) 609{ 610 Mutex::Autolock _l(mLock); 611 if(!modifyAudioRoutingAllowed()) { 612 return PERMISSION_DENIED; 613 } 614 if (mAudioPolicyManager == NULL) { 615 return NO_INIT; 616 } 617 618 return mAudioPolicyManager->releaseAudioPatch(handle, 619 IPCThreadState::self()->getCallingUid()); 620} 621 622status_t AudioPolicyService::listAudioPatches(unsigned int *num_patches, 623 struct audio_patch *patches, 624 unsigned int *generation) 625{ 626 Mutex::Autolock _l(mLock); 627 if (mAudioPolicyManager == NULL) { 628 return NO_INIT; 629 } 630 631 return mAudioPolicyManager->listAudioPatches(num_patches, patches, generation); 632} 633 634status_t AudioPolicyService::setAudioPortConfig(const struct audio_port_config *config) 635{ 636 Mutex::Autolock _l(mLock); 637 if(!modifyAudioRoutingAllowed()) { 638 return PERMISSION_DENIED; 639 } 640 if (mAudioPolicyManager == NULL) { 641 return NO_INIT; 642 } 643 644 return mAudioPolicyManager->setAudioPortConfig(config); 645} 646 647status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session, 648 audio_io_handle_t *ioHandle, 649 audio_devices_t *device) 650{ 651 if (mAudioPolicyManager == NULL) { 652 return NO_INIT; 653 } 654 655 return mAudioPolicyManager->acquireSoundTriggerSession(session, ioHandle, device); 656} 657 658status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session) 659{ 660 if (mAudioPolicyManager == NULL) { 661 return NO_INIT; 662 } 663 664 return mAudioPolicyManager->releaseSoundTriggerSession(session); 665} 666 667status_t AudioPolicyService::registerPolicyMixes(Vector<AudioMix> mixes, bool registration) 668{ 669 Mutex::Autolock _l(mLock); 670 if(!modifyAudioRoutingAllowed()) { 671 return PERMISSION_DENIED; 672 } 673 if (mAudioPolicyManager == NULL) { 674 return NO_INIT; 675 } 676 if (registration) { 677 return mAudioPolicyManager->registerPolicyMixes(mixes); 678 } else { 679 return mAudioPolicyManager->unregisterPolicyMixes(mixes); 680 } 681} 682 683status_t AudioPolicyService::startAudioSource(const struct audio_port_config *source, 684 const audio_attributes_t *attributes, 685 audio_io_handle_t *handle) 686{ 687 Mutex::Autolock _l(mLock); 688 if (mAudioPolicyManager == NULL) { 689 return NO_INIT; 690 } 691 692 return mAudioPolicyManager->startAudioSource(source, attributes, handle); 693} 694 695status_t AudioPolicyService::stopAudioSource(audio_io_handle_t handle) 696{ 697 Mutex::Autolock _l(mLock); 698 if (mAudioPolicyManager == NULL) { 699 return NO_INIT; 700 } 701 702 return mAudioPolicyManager->stopAudioSource(handle); 703} 704 705}; // namespace android 706