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