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