AudioPolicyInterfaceImpl.cpp revision dfb9f3b053fa8ff7e622783a2040953442c44700
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    Mutex::Autolock _l(mLock);
463    return mAudioPolicyManager->getDevicesForStream(stream);
464}
465
466audio_io_handle_t AudioPolicyService::getOutputForEffect(const effect_descriptor_t *desc)
467{
468    // FIXME change return type to status_t, and return NO_INIT here
469    if (mAudioPolicyManager == NULL) {
470        return 0;
471    }
472    Mutex::Autolock _l(mLock);
473    return mAudioPolicyManager->getOutputForEffect(desc);
474}
475
476status_t AudioPolicyService::registerEffect(const effect_descriptor_t *desc,
477                                audio_io_handle_t io,
478                                uint32_t strategy,
479                                int session,
480                                int id)
481{
482    if (mAudioPolicyManager == NULL) {
483        return NO_INIT;
484    }
485    return mAudioPolicyManager->registerEffect(desc, io, strategy, session, id);
486}
487
488status_t AudioPolicyService::unregisterEffect(int id)
489{
490    if (mAudioPolicyManager == NULL) {
491        return NO_INIT;
492    }
493    return mAudioPolicyManager->unregisterEffect(id);
494}
495
496status_t AudioPolicyService::setEffectEnabled(int id, bool enabled)
497{
498    if (mAudioPolicyManager == NULL) {
499        return NO_INIT;
500    }
501    return mAudioPolicyManager->setEffectEnabled(id, enabled);
502}
503
504bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
505{
506    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
507        return false;
508    }
509    if (mAudioPolicyManager == NULL) {
510        return false;
511    }
512    Mutex::Autolock _l(mLock);
513    return mAudioPolicyManager->isStreamActive(stream, inPastMs);
514}
515
516bool AudioPolicyService::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
517{
518    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
519        return false;
520    }
521    if (mAudioPolicyManager == NULL) {
522        return false;
523    }
524    Mutex::Autolock _l(mLock);
525    return mAudioPolicyManager->isStreamActiveRemotely(stream, inPastMs);
526}
527
528bool AudioPolicyService::isSourceActive(audio_source_t source) const
529{
530    if (mAudioPolicyManager == NULL) {
531        return false;
532    }
533    Mutex::Autolock _l(mLock);
534    return mAudioPolicyManager->isSourceActive(source);
535}
536
537status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
538                                                       effect_descriptor_t *descriptors,
539                                                       uint32_t *count)
540{
541    if (mAudioPolicyManager == NULL) {
542        *count = 0;
543        return NO_INIT;
544    }
545    sp<AudioPolicyEffects>audioPolicyEffects;
546    {
547        Mutex::Autolock _l(mLock);
548        audioPolicyEffects = mAudioPolicyEffects;
549    }
550    if (audioPolicyEffects == 0) {
551        *count = 0;
552        return NO_INIT;
553    }
554    return audioPolicyEffects->queryDefaultInputEffects(audioSession, descriptors, count);
555}
556
557bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info)
558{
559    if (mAudioPolicyManager == NULL) {
560        ALOGV("mAudioPolicyManager == NULL");
561        return false;
562    }
563
564    return mAudioPolicyManager->isOffloadSupported(info);
565}
566
567status_t AudioPolicyService::listAudioPorts(audio_port_role_t role,
568                                            audio_port_type_t type,
569                                            unsigned int *num_ports,
570                                            struct audio_port *ports,
571                                            unsigned int *generation)
572{
573    Mutex::Autolock _l(mLock);
574    if (mAudioPolicyManager == NULL) {
575        return NO_INIT;
576    }
577
578    return mAudioPolicyManager->listAudioPorts(role, type, num_ports, ports, generation);
579}
580
581status_t AudioPolicyService::getAudioPort(struct audio_port *port)
582{
583    Mutex::Autolock _l(mLock);
584    if (mAudioPolicyManager == NULL) {
585        return NO_INIT;
586    }
587
588    return mAudioPolicyManager->getAudioPort(port);
589}
590
591status_t AudioPolicyService::createAudioPatch(const struct audio_patch *patch,
592        audio_patch_handle_t *handle)
593{
594    Mutex::Autolock _l(mLock);
595    if(!modifyAudioRoutingAllowed()) {
596        return PERMISSION_DENIED;
597    }
598    if (mAudioPolicyManager == NULL) {
599        return NO_INIT;
600    }
601    return mAudioPolicyManager->createAudioPatch(patch, handle,
602                                                  IPCThreadState::self()->getCallingUid());
603}
604
605status_t AudioPolicyService::releaseAudioPatch(audio_patch_handle_t handle)
606{
607    Mutex::Autolock _l(mLock);
608    if(!modifyAudioRoutingAllowed()) {
609        return PERMISSION_DENIED;
610    }
611    if (mAudioPolicyManager == NULL) {
612        return NO_INIT;
613    }
614
615    return mAudioPolicyManager->releaseAudioPatch(handle,
616                                                     IPCThreadState::self()->getCallingUid());
617}
618
619status_t AudioPolicyService::listAudioPatches(unsigned int *num_patches,
620        struct audio_patch *patches,
621        unsigned int *generation)
622{
623    Mutex::Autolock _l(mLock);
624    if (mAudioPolicyManager == NULL) {
625        return NO_INIT;
626    }
627
628    return mAudioPolicyManager->listAudioPatches(num_patches, patches, generation);
629}
630
631status_t AudioPolicyService::setAudioPortConfig(const struct audio_port_config *config)
632{
633    Mutex::Autolock _l(mLock);
634    if(!modifyAudioRoutingAllowed()) {
635        return PERMISSION_DENIED;
636    }
637    if (mAudioPolicyManager == NULL) {
638        return NO_INIT;
639    }
640
641    return mAudioPolicyManager->setAudioPortConfig(config);
642}
643
644status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session,
645                                       audio_io_handle_t *ioHandle,
646                                       audio_devices_t *device)
647{
648    if (mAudioPolicyManager == NULL) {
649        return NO_INIT;
650    }
651
652    return mAudioPolicyManager->acquireSoundTriggerSession(session, ioHandle, device);
653}
654
655status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session)
656{
657    if (mAudioPolicyManager == NULL) {
658        return NO_INIT;
659    }
660
661    return mAudioPolicyManager->releaseSoundTriggerSession(session);
662}
663
664status_t AudioPolicyService::registerPolicyMixes(Vector<AudioMix> mixes, bool registration)
665{
666    Mutex::Autolock _l(mLock);
667    if(!modifyAudioRoutingAllowed()) {
668        return PERMISSION_DENIED;
669    }
670    if (mAudioPolicyManager == NULL) {
671        return NO_INIT;
672    }
673    if (registration) {
674        return mAudioPolicyManager->registerPolicyMixes(mixes);
675    } else {
676        return mAudioPolicyManager->unregisterPolicyMixes(mixes);
677    }
678}
679
680status_t AudioPolicyService::startAudioSource(const struct audio_port_config *source,
681                                  const audio_attributes_t *attributes,
682                                  audio_io_handle_t *handle)
683{
684    Mutex::Autolock _l(mLock);
685    if (mAudioPolicyManager == NULL) {
686        return NO_INIT;
687    }
688
689    return mAudioPolicyManager->startAudioSource(source, attributes, handle);
690}
691
692status_t AudioPolicyService::stopAudioSource(audio_io_handle_t handle)
693{
694    Mutex::Autolock _l(mLock);
695    if (mAudioPolicyManager == NULL) {
696        return NO_INIT;
697    }
698
699    return mAudioPolicyManager->stopAudioSource(handle);
700}
701
702}; // namespace android
703