AudioPolicyService.cpp revision f78aee70d15daf4690de7e7b4983ee68b0d1381d
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "AudioPolicyService"
18//#define LOG_NDEBUG 0
19
20#undef __STRICT_ANSI__
21#define __STDINT_LIMITS
22#define __STDC_LIMIT_MACROS
23#include <stdint.h>
24
25#include <sys/time.h>
26#include <binder/IServiceManager.h>
27#include <utils/Log.h>
28#include <cutils/properties.h>
29#include <binder/IPCThreadState.h>
30#include <utils/String16.h>
31#include <utils/threads.h>
32#include "AudioPolicyService.h"
33#include <cutils/properties.h>
34#include <hardware_legacy/power.h>
35#include <media/AudioEffect.h>
36#include <media/EffectsFactoryApi.h>
37
38#include <hardware/hardware.h>
39#include <system/audio.h>
40#include <system/audio_policy.h>
41#include <hardware/audio_policy.h>
42#include <audio_effects/audio_effects_conf.h>
43
44namespace android {
45
46static const char *kDeadlockedString = "AudioPolicyService may be deadlocked\n";
47static const char *kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
48
49static const int kDumpLockRetries = 50;
50static const int kDumpLockSleep = 20000;
51
52static bool checkPermission() {
53    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
54    bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
55    if (!ok) ALOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
56    return ok;
57}
58
59namespace {
60    extern struct audio_policy_service_ops aps_ops;
61};
62
63// ----------------------------------------------------------------------------
64
65AudioPolicyService::AudioPolicyService()
66    : BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)
67{
68    char value[PROPERTY_VALUE_MAX];
69    const struct hw_module_t *module;
70    int forced_val;
71    int rc;
72
73    Mutex::Autolock _l(mLock);
74
75    // start tone playback thread
76    mTonePlaybackThread = new AudioCommandThread(String8(""));
77    // start audio commands thread
78    mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread"));
79
80    /* instantiate the audio policy manager */
81    rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
82    if (rc)
83        return;
84
85    rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
86    ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
87    if (rc)
88        return;
89
90    rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
91                                               &mpAudioPolicy);
92    ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
93    if (rc)
94        return;
95
96    rc = mpAudioPolicy->init_check(mpAudioPolicy);
97    ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
98    if (rc)
99        return;
100
101    property_get("ro.camera.sound.forced", value, "0");
102    forced_val = strtol(value, NULL, 0);
103    mpAudioPolicy->set_can_mute_enforced_audible(mpAudioPolicy, !forced_val);
104
105    ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
106
107    // load audio pre processing modules
108    if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
109        loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
110    } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
111        loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
112    }
113}
114
115AudioPolicyService::~AudioPolicyService()
116{
117    mTonePlaybackThread->exit();
118    mTonePlaybackThread.clear();
119    mAudioCommandThread->exit();
120    mAudioCommandThread.clear();
121
122
123    // release audio pre processing resources
124    for (size_t i = 0; i < mInputSources.size(); i++) {
125        InputSourceDesc *source = mInputSources.valueAt(i);
126        Vector <EffectDesc *> effects = source->mEffects;
127        for (size_t j = 0; j < effects.size(); j++) {
128            delete effects[j]->mName;
129            Vector <effect_param_t *> params = effects[j]->mParams;
130            for (size_t k = 0; k < params.size(); k++) {
131                delete params[k];
132            }
133            params.clear();
134            delete effects[j];
135        }
136        effects.clear();
137        delete source;
138    }
139    mInputSources.clear();
140
141    for (size_t i = 0; i < mInputs.size(); i++) {
142        mInputs.valueAt(i)->mEffects.clear();
143        delete mInputs.valueAt(i);
144    }
145    mInputs.clear();
146
147    if (mpAudioPolicy && mpAudioPolicyDev)
148        mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy);
149    if (mpAudioPolicyDev)
150        audio_policy_dev_close(mpAudioPolicyDev);
151}
152
153status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
154                                                  audio_policy_dev_state_t state,
155                                                  const char *device_address)
156{
157    if (mpAudioPolicy == NULL) {
158        return NO_INIT;
159    }
160    if (!checkPermission()) {
161        return PERMISSION_DENIED;
162    }
163    if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
164        return BAD_VALUE;
165    }
166    if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE &&
167            state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
168        return BAD_VALUE;
169    }
170
171    ALOGV("setDeviceConnectionState() tid %d", gettid());
172    Mutex::Autolock _l(mLock);
173    return mpAudioPolicy->set_device_connection_state(mpAudioPolicy, device,
174                                                      state, device_address);
175}
176
177audio_policy_dev_state_t AudioPolicyService::getDeviceConnectionState(
178                                                              audio_devices_t device,
179                                                              const char *device_address)
180{
181    if (mpAudioPolicy == NULL) {
182        return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
183    }
184    return mpAudioPolicy->get_device_connection_state(mpAudioPolicy, device,
185                                                      device_address);
186}
187
188status_t AudioPolicyService::setPhoneState(audio_mode_t state)
189{
190    if (mpAudioPolicy == NULL) {
191        return NO_INIT;
192    }
193    if (!checkPermission()) {
194        return PERMISSION_DENIED;
195    }
196    if (uint32_t(state) >= AUDIO_MODE_CNT) {
197        return BAD_VALUE;
198    }
199
200    ALOGV("setPhoneState() tid %d", gettid());
201
202    // TODO: check if it is more appropriate to do it in platform specific policy manager
203    AudioSystem::setMode(state);
204
205    Mutex::Autolock _l(mLock);
206    mpAudioPolicy->set_phone_state(mpAudioPolicy, state);
207    return NO_ERROR;
208}
209
210status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
211{
212    if (mpAudioPolicy == NULL) {
213        return NO_INIT;
214    }
215    if (!checkPermission()) {
216        return PERMISSION_DENIED;
217    }
218
219    mpAudioPolicy->set_ringer_mode(mpAudioPolicy, mode, mask);
220    return NO_ERROR;
221}
222
223status_t AudioPolicyService::setForceUse(audio_policy_force_use_t usage,
224                                         audio_policy_forced_cfg_t config)
225{
226    if (mpAudioPolicy == NULL) {
227        return NO_INIT;
228    }
229    if (!checkPermission()) {
230        return PERMISSION_DENIED;
231    }
232    if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
233        return BAD_VALUE;
234    }
235    if (config < 0 || config >= AUDIO_POLICY_FORCE_CFG_CNT) {
236        return BAD_VALUE;
237    }
238    ALOGV("setForceUse() tid %d", gettid());
239    Mutex::Autolock _l(mLock);
240    mpAudioPolicy->set_force_use(mpAudioPolicy, usage, config);
241    return NO_ERROR;
242}
243
244audio_policy_forced_cfg_t AudioPolicyService::getForceUse(audio_policy_force_use_t usage)
245{
246    if (mpAudioPolicy == NULL) {
247        return AUDIO_POLICY_FORCE_NONE;
248    }
249    if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
250        return AUDIO_POLICY_FORCE_NONE;
251    }
252    return mpAudioPolicy->get_force_use(mpAudioPolicy, usage);
253}
254
255audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream,
256                                    uint32_t samplingRate,
257                                    uint32_t format,
258                                    uint32_t channels,
259                                    audio_policy_output_flags_t flags)
260{
261    if (mpAudioPolicy == NULL) {
262        return 0;
263    }
264    ALOGV("getOutput() tid %d", gettid());
265    Mutex::Autolock _l(mLock);
266    return mpAudioPolicy->get_output(mpAudioPolicy, stream, samplingRate, format, channels, flags);
267}
268
269status_t AudioPolicyService::startOutput(audio_io_handle_t output,
270                                         audio_stream_type_t stream,
271                                         int session)
272{
273    if (mpAudioPolicy == NULL) {
274        return NO_INIT;
275    }
276    ALOGV("startOutput() tid %d", gettid());
277    Mutex::Autolock _l(mLock);
278    return mpAudioPolicy->start_output(mpAudioPolicy, output, stream, session);
279}
280
281status_t AudioPolicyService::stopOutput(audio_io_handle_t output,
282                                        audio_stream_type_t stream,
283                                        int session)
284{
285    if (mpAudioPolicy == NULL) {
286        return NO_INIT;
287    }
288    ALOGV("stopOutput() tid %d", gettid());
289    Mutex::Autolock _l(mLock);
290    return mpAudioPolicy->stop_output(mpAudioPolicy, output, stream, session);
291}
292
293void AudioPolicyService::releaseOutput(audio_io_handle_t output)
294{
295    if (mpAudioPolicy == NULL) {
296        return;
297    }
298    ALOGV("releaseOutput() tid %d", gettid());
299    Mutex::Autolock _l(mLock);
300    mpAudioPolicy->release_output(mpAudioPolicy, output);
301}
302
303audio_io_handle_t AudioPolicyService::getInput(int inputSource,
304                                    uint32_t samplingRate,
305                                    uint32_t format,
306                                    uint32_t channels,
307                                    audio_in_acoustics_t acoustics,
308                                    int audioSession)
309{
310    if (mpAudioPolicy == NULL) {
311        return 0;
312    }
313    Mutex::Autolock _l(mLock);
314    audio_io_handle_t input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
315                                                       format, channels, acoustics);
316
317    if (input == 0) {
318        return input;
319    }
320    // create audio pre processors according to input source
321    ssize_t index = mInputSources.indexOfKey((audio_source_t)inputSource);
322    if (index < 0) {
323        return input;
324    }
325    ssize_t idx = mInputs.indexOfKey(input);
326    InputDesc *inputDesc;
327    if (idx < 0) {
328        inputDesc = new InputDesc();
329        inputDesc->mSessionId = audioSession;
330        mInputs.add(input, inputDesc);
331    } else {
332        inputDesc = mInputs.valueAt(idx);
333    }
334
335    Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
336    for (size_t i = 0; i < effects.size(); i++) {
337        EffectDesc *effect = effects[i];
338        sp<AudioEffect> fx = new AudioEffect(NULL, &effect->mUuid, -1, 0, 0, audioSession, input);
339        status_t status = fx->initCheck();
340        if (status != NO_ERROR && status != ALREADY_EXISTS) {
341            ALOGW("Failed to create Fx %s on input %d", effect->mName, input);
342            // fx goes out of scope and strong ref on AudioEffect is released
343            continue;
344        }
345        for (size_t j = 0; j < effect->mParams.size(); j++) {
346            fx->setParameter(effect->mParams[j]);
347        }
348        inputDesc->mEffects.add(fx);
349    }
350    setPreProcessorEnabled(inputDesc, true);
351    return input;
352}
353
354status_t AudioPolicyService::startInput(audio_io_handle_t input)
355{
356    if (mpAudioPolicy == NULL) {
357        return NO_INIT;
358    }
359    Mutex::Autolock _l(mLock);
360
361    return mpAudioPolicy->start_input(mpAudioPolicy, input);
362}
363
364status_t AudioPolicyService::stopInput(audio_io_handle_t input)
365{
366    if (mpAudioPolicy == NULL) {
367        return NO_INIT;
368    }
369    Mutex::Autolock _l(mLock);
370
371    return mpAudioPolicy->stop_input(mpAudioPolicy, input);
372}
373
374void AudioPolicyService::releaseInput(audio_io_handle_t input)
375{
376    if (mpAudioPolicy == NULL) {
377        return;
378    }
379    Mutex::Autolock _l(mLock);
380    mpAudioPolicy->release_input(mpAudioPolicy, input);
381
382    ssize_t index = mInputs.indexOfKey(input);
383    if (index < 0) {
384        return;
385    }
386    InputDesc *inputDesc = mInputs.valueAt(index);
387    setPreProcessorEnabled(inputDesc, false);
388    inputDesc->mEffects.clear();
389    delete inputDesc;
390    mInputs.removeItemsAt(index);
391}
392
393status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream,
394                                            int indexMin,
395                                            int indexMax)
396{
397    if (mpAudioPolicy == NULL) {
398        return NO_INIT;
399    }
400    if (!checkPermission()) {
401        return PERMISSION_DENIED;
402    }
403    if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
404        return BAD_VALUE;
405    }
406    mpAudioPolicy->init_stream_volume(mpAudioPolicy, stream, indexMin, indexMax);
407    return NO_ERROR;
408}
409
410status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream, int index)
411{
412    if (mpAudioPolicy == NULL) {
413        return NO_INIT;
414    }
415    if (!checkPermission()) {
416        return PERMISSION_DENIED;
417    }
418    if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
419        return BAD_VALUE;
420    }
421
422    return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index);
423}
424
425status_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream, int *index)
426{
427    if (mpAudioPolicy == NULL) {
428        return NO_INIT;
429    }
430    if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
431        return BAD_VALUE;
432    }
433    return mpAudioPolicy->get_stream_volume_index(mpAudioPolicy, stream, index);
434}
435
436uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream)
437{
438    if (mpAudioPolicy == NULL) {
439        return 0;
440    }
441    return mpAudioPolicy->get_strategy_for_stream(mpAudioPolicy, stream);
442}
443
444uint32_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
445{
446    if (mpAudioPolicy == NULL) {
447        return 0;
448    }
449    return mpAudioPolicy->get_devices_for_stream(mpAudioPolicy, stream);
450}
451
452audio_io_handle_t AudioPolicyService::getOutputForEffect(effect_descriptor_t *desc)
453{
454    if (mpAudioPolicy == NULL) {
455        return NO_INIT;
456    }
457    Mutex::Autolock _l(mLock);
458    return mpAudioPolicy->get_output_for_effect(mpAudioPolicy, desc);
459}
460
461status_t AudioPolicyService::registerEffect(effect_descriptor_t *desc,
462                                audio_io_handle_t io,
463                                uint32_t strategy,
464                                int session,
465                                int id)
466{
467    if (mpAudioPolicy == NULL) {
468        return NO_INIT;
469    }
470    return mpAudioPolicy->register_effect(mpAudioPolicy, desc, io, strategy, session, id);
471}
472
473status_t AudioPolicyService::unregisterEffect(int id)
474{
475    if (mpAudioPolicy == NULL) {
476        return NO_INIT;
477    }
478    return mpAudioPolicy->unregister_effect(mpAudioPolicy, id);
479}
480
481status_t AudioPolicyService::setEffectEnabled(int id, bool enabled)
482{
483    if (mpAudioPolicy == NULL) {
484        return NO_INIT;
485    }
486    return mpAudioPolicy->set_effect_enabled(mpAudioPolicy, id, enabled);
487}
488
489bool AudioPolicyService::isStreamActive(int stream, uint32_t inPastMs) const
490{
491    if (mpAudioPolicy == NULL) {
492        return 0;
493    }
494    Mutex::Autolock _l(mLock);
495    return mpAudioPolicy->is_stream_active(mpAudioPolicy, stream, inPastMs);
496}
497
498status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
499                                                       effect_descriptor_t *descriptors,
500                                                       uint32_t *count)
501{
502
503    if (mpAudioPolicy == NULL) {
504        *count = 0;
505        return NO_INIT;
506    }
507    Mutex::Autolock _l(mLock);
508    status_t status = NO_ERROR;
509
510    size_t index;
511    for (index = 0; index < mInputs.size(); index++) {
512        if (mInputs.valueAt(index)->mSessionId == audioSession) {
513            break;
514        }
515    }
516    if (index == mInputs.size()) {
517        *count = 0;
518        return BAD_VALUE;
519    }
520    Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects;
521
522    for (size_t i = 0; i < effects.size(); i++) {
523        effect_descriptor_t desc = effects[i]->descriptor();
524        if (i < *count) {
525            memcpy(descriptors + i, &desc, sizeof(effect_descriptor_t));
526        }
527    }
528    if (effects.size() > *count) {
529        status = NO_MEMORY;
530    }
531    *count = effects.size();
532    return status;
533}
534
535void AudioPolicyService::binderDied(const wp<IBinder>& who) {
536    ALOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(),
537            IPCThreadState::self()->getCallingPid());
538}
539
540static bool tryLock(Mutex& mutex)
541{
542    bool locked = false;
543    for (int i = 0; i < kDumpLockRetries; ++i) {
544        if (mutex.tryLock() == NO_ERROR) {
545            locked = true;
546            break;
547        }
548        usleep(kDumpLockSleep);
549    }
550    return locked;
551}
552
553status_t AudioPolicyService::dumpInternals(int fd)
554{
555    const size_t SIZE = 256;
556    char buffer[SIZE];
557    String8 result;
558
559    snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpAudioPolicy);
560    result.append(buffer);
561    snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
562    result.append(buffer);
563    snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
564    result.append(buffer);
565
566    write(fd, result.string(), result.size());
567    return NO_ERROR;
568}
569
570status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
571{
572    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
573        dumpPermissionDenial(fd);
574    } else {
575        bool locked = tryLock(mLock);
576        if (!locked) {
577            String8 result(kDeadlockedString);
578            write(fd, result.string(), result.size());
579        }
580
581        dumpInternals(fd);
582        if (mAudioCommandThread != NULL) {
583            mAudioCommandThread->dump(fd);
584        }
585        if (mTonePlaybackThread != NULL) {
586            mTonePlaybackThread->dump(fd);
587        }
588
589        if (mpAudioPolicy) {
590            mpAudioPolicy->dump(mpAudioPolicy, fd);
591        }
592
593        if (locked) mLock.unlock();
594    }
595    return NO_ERROR;
596}
597
598status_t AudioPolicyService::dumpPermissionDenial(int fd)
599{
600    const size_t SIZE = 256;
601    char buffer[SIZE];
602    String8 result;
603    snprintf(buffer, SIZE, "Permission Denial: "
604            "can't dump AudioPolicyService from pid=%d, uid=%d\n",
605            IPCThreadState::self()->getCallingPid(),
606            IPCThreadState::self()->getCallingUid());
607    result.append(buffer);
608    write(fd, result.string(), result.size());
609    return NO_ERROR;
610}
611
612void AudioPolicyService::setPreProcessorEnabled(InputDesc *inputDesc, bool enabled)
613{
614    Vector<sp<AudioEffect> > fxVector = inputDesc->mEffects;
615    for (size_t i = 0; i < fxVector.size(); i++) {
616        sp<AudioEffect> fx = fxVector.itemAt(i);
617        fx->setEnabled(enabled);
618    }
619}
620
621status_t AudioPolicyService::onTransact(
622        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
623{
624    return BnAudioPolicyService::onTransact(code, data, reply, flags);
625}
626
627
628// -----------  AudioPolicyService::AudioCommandThread implementation ----------
629
630AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name)
631    : Thread(false), mName(name)
632{
633    mpToneGenerator = NULL;
634}
635
636
637AudioPolicyService::AudioCommandThread::~AudioCommandThread()
638{
639    if (mName != "" && !mAudioCommands.isEmpty()) {
640        release_wake_lock(mName.string());
641    }
642    mAudioCommands.clear();
643    if (mpToneGenerator != NULL) delete mpToneGenerator;
644}
645
646void AudioPolicyService::AudioCommandThread::onFirstRef()
647{
648    if (mName != "") {
649        run(mName.string(), ANDROID_PRIORITY_AUDIO);
650    } else {
651        run("AudioCommandThread", ANDROID_PRIORITY_AUDIO);
652    }
653}
654
655bool AudioPolicyService::AudioCommandThread::threadLoop()
656{
657    nsecs_t waitTime = INT64_MAX;
658
659    mLock.lock();
660    while (!exitPending())
661    {
662        while(!mAudioCommands.isEmpty()) {
663            nsecs_t curTime = systemTime();
664            // commands are sorted by increasing time stamp: execute them from index 0 and up
665            if (mAudioCommands[0]->mTime <= curTime) {
666                AudioCommand *command = mAudioCommands[0];
667                mAudioCommands.removeAt(0);
668                mLastCommand = *command;
669
670                switch (command->mCommand) {
671                case START_TONE: {
672                    mLock.unlock();
673                    ToneData *data = (ToneData *)command->mParam;
674                    ALOGV("AudioCommandThread() processing start tone %d on stream %d",
675                            data->mType, data->mStream);
676                    if (mpToneGenerator != NULL)
677                        delete mpToneGenerator;
678                    mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
679                    mpToneGenerator->startTone(data->mType);
680                    delete data;
681                    mLock.lock();
682                    }break;
683                case STOP_TONE: {
684                    mLock.unlock();
685                    ALOGV("AudioCommandThread() processing stop tone");
686                    if (mpToneGenerator != NULL) {
687                        mpToneGenerator->stopTone();
688                        delete mpToneGenerator;
689                        mpToneGenerator = NULL;
690                    }
691                    mLock.lock();
692                    }break;
693                case SET_VOLUME: {
694                    VolumeData *data = (VolumeData *)command->mParam;
695                    ALOGV("AudioCommandThread() processing set volume stream %d, \
696                            volume %f, output %d", data->mStream, data->mVolume, data->mIO);
697                    command->mStatus = AudioSystem::setStreamVolume(data->mStream,
698                                                                    data->mVolume,
699                                                                    data->mIO);
700                    if (command->mWaitStatus) {
701                        command->mCond.signal();
702                        mWaitWorkCV.wait(mLock);
703                    }
704                    delete data;
705                    }break;
706                case SET_PARAMETERS: {
707                     ParametersData *data = (ParametersData *)command->mParam;
708                     ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
709                             data->mKeyValuePairs.string(), data->mIO);
710                     command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
711                     if (command->mWaitStatus) {
712                         command->mCond.signal();
713                         mWaitWorkCV.wait(mLock);
714                     }
715                     delete data;
716                     }break;
717                case SET_VOICE_VOLUME: {
718                    VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
719                    ALOGV("AudioCommandThread() processing set voice volume volume %f",
720                            data->mVolume);
721                    command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
722                    if (command->mWaitStatus) {
723                        command->mCond.signal();
724                        mWaitWorkCV.wait(mLock);
725                    }
726                    delete data;
727                    }break;
728                default:
729                    ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
730                }
731                delete command;
732                waitTime = INT64_MAX;
733            } else {
734                waitTime = mAudioCommands[0]->mTime - curTime;
735                break;
736            }
737        }
738        // release delayed commands wake lock
739        if (mName != "" && mAudioCommands.isEmpty()) {
740            release_wake_lock(mName.string());
741        }
742        ALOGV("AudioCommandThread() going to sleep");
743        mWaitWorkCV.waitRelative(mLock, waitTime);
744        ALOGV("AudioCommandThread() waking up");
745    }
746    mLock.unlock();
747    return false;
748}
749
750status_t AudioPolicyService::AudioCommandThread::dump(int fd)
751{
752    const size_t SIZE = 256;
753    char buffer[SIZE];
754    String8 result;
755
756    snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
757    result.append(buffer);
758    write(fd, result.string(), result.size());
759
760    bool locked = tryLock(mLock);
761    if (!locked) {
762        String8 result2(kCmdDeadlockedString);
763        write(fd, result2.string(), result2.size());
764    }
765
766    snprintf(buffer, SIZE, "- Commands:\n");
767    result = String8(buffer);
768    result.append("   Command Time        Wait pParam\n");
769    for (int i = 0; i < (int)mAudioCommands.size(); i++) {
770        mAudioCommands[i]->dump(buffer, SIZE);
771        result.append(buffer);
772    }
773    result.append("  Last Command\n");
774    mLastCommand.dump(buffer, SIZE);
775    result.append(buffer);
776
777    write(fd, result.string(), result.size());
778
779    if (locked) mLock.unlock();
780
781    return NO_ERROR;
782}
783
784void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
785{
786    AudioCommand *command = new AudioCommand();
787    command->mCommand = START_TONE;
788    ToneData *data = new ToneData();
789    data->mType = type;
790    data->mStream = stream;
791    command->mParam = (void *)data;
792    command->mWaitStatus = false;
793    Mutex::Autolock _l(mLock);
794    insertCommand_l(command);
795    ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
796    mWaitWorkCV.signal();
797}
798
799void AudioPolicyService::AudioCommandThread::stopToneCommand()
800{
801    AudioCommand *command = new AudioCommand();
802    command->mCommand = STOP_TONE;
803    command->mParam = NULL;
804    command->mWaitStatus = false;
805    Mutex::Autolock _l(mLock);
806    insertCommand_l(command);
807    ALOGV("AudioCommandThread() adding tone stop");
808    mWaitWorkCV.signal();
809}
810
811status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream,
812                                                               float volume,
813                                                               int output,
814                                                               int delayMs)
815{
816    status_t status = NO_ERROR;
817
818    AudioCommand *command = new AudioCommand();
819    command->mCommand = SET_VOLUME;
820    VolumeData *data = new VolumeData();
821    data->mStream = stream;
822    data->mVolume = volume;
823    data->mIO = output;
824    command->mParam = data;
825    if (delayMs == 0) {
826        command->mWaitStatus = true;
827    } else {
828        command->mWaitStatus = false;
829    }
830    Mutex::Autolock _l(mLock);
831    insertCommand_l(command, delayMs);
832    ALOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d",
833            stream, volume, output);
834    mWaitWorkCV.signal();
835    if (command->mWaitStatus) {
836        command->mCond.wait(mLock);
837        status =  command->mStatus;
838        mWaitWorkCV.signal();
839    }
840    return status;
841}
842
843status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle,
844                                                                   const char *keyValuePairs,
845                                                                   int delayMs)
846{
847    status_t status = NO_ERROR;
848
849    AudioCommand *command = new AudioCommand();
850    command->mCommand = SET_PARAMETERS;
851    ParametersData *data = new ParametersData();
852    data->mIO = ioHandle;
853    data->mKeyValuePairs = String8(keyValuePairs);
854    command->mParam = data;
855    if (delayMs == 0) {
856        command->mWaitStatus = true;
857    } else {
858        command->mWaitStatus = false;
859    }
860    Mutex::Autolock _l(mLock);
861    insertCommand_l(command, delayMs);
862    ALOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d",
863            keyValuePairs, ioHandle, delayMs);
864    mWaitWorkCV.signal();
865    if (command->mWaitStatus) {
866        command->mCond.wait(mLock);
867        status =  command->mStatus;
868        mWaitWorkCV.signal();
869    }
870    return status;
871}
872
873status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
874{
875    status_t status = NO_ERROR;
876
877    AudioCommand *command = new AudioCommand();
878    command->mCommand = SET_VOICE_VOLUME;
879    VoiceVolumeData *data = new VoiceVolumeData();
880    data->mVolume = volume;
881    command->mParam = data;
882    if (delayMs == 0) {
883        command->mWaitStatus = true;
884    } else {
885        command->mWaitStatus = false;
886    }
887    Mutex::Autolock _l(mLock);
888    insertCommand_l(command, delayMs);
889    ALOGV("AudioCommandThread() adding set voice volume volume %f", volume);
890    mWaitWorkCV.signal();
891    if (command->mWaitStatus) {
892        command->mCond.wait(mLock);
893        status =  command->mStatus;
894        mWaitWorkCV.signal();
895    }
896    return status;
897}
898
899// insertCommand_l() must be called with mLock held
900void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
901{
902    ssize_t i;
903    Vector <AudioCommand *> removedCommands;
904
905    command->mTime = systemTime() + milliseconds(delayMs);
906
907    // acquire wake lock to make sure delayed commands are processed
908    if (mName != "" && mAudioCommands.isEmpty()) {
909        acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
910    }
911
912    // check same pending commands with later time stamps and eliminate them
913    for (i = mAudioCommands.size()-1; i >= 0; i--) {
914        AudioCommand *command2 = mAudioCommands[i];
915        // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
916        if (command2->mTime <= command->mTime) break;
917        if (command2->mCommand != command->mCommand) continue;
918
919        switch (command->mCommand) {
920        case SET_PARAMETERS: {
921            ParametersData *data = (ParametersData *)command->mParam;
922            ParametersData *data2 = (ParametersData *)command2->mParam;
923            if (data->mIO != data2->mIO) break;
924            ALOGV("Comparing parameter command %s to new command %s",
925                    data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
926            AudioParameter param = AudioParameter(data->mKeyValuePairs);
927            AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
928            for (size_t j = 0; j < param.size(); j++) {
929               String8 key;
930               String8 value;
931               param.getAt(j, key, value);
932               for (size_t k = 0; k < param2.size(); k++) {
933                  String8 key2;
934                  String8 value2;
935                  param2.getAt(k, key2, value2);
936                  if (key2 == key) {
937                      param2.remove(key2);
938                      ALOGV("Filtering out parameter %s", key2.string());
939                      break;
940                  }
941               }
942            }
943            // if all keys have been filtered out, remove the command.
944            // otherwise, update the key value pairs
945            if (param2.size() == 0) {
946                removedCommands.add(command2);
947            } else {
948                data2->mKeyValuePairs = param2.toString();
949            }
950        } break;
951
952        case SET_VOLUME: {
953            VolumeData *data = (VolumeData *)command->mParam;
954            VolumeData *data2 = (VolumeData *)command2->mParam;
955            if (data->mIO != data2->mIO) break;
956            if (data->mStream != data2->mStream) break;
957            ALOGV("Filtering out volume command on output %d for stream %d",
958                    data->mIO, data->mStream);
959            removedCommands.add(command2);
960        } break;
961        case START_TONE:
962        case STOP_TONE:
963        default:
964            break;
965        }
966    }
967
968    // remove filtered commands
969    for (size_t j = 0; j < removedCommands.size(); j++) {
970        // removed commands always have time stamps greater than current command
971        for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
972            if (mAudioCommands[k] == removedCommands[j]) {
973                ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
974                mAudioCommands.removeAt(k);
975                break;
976            }
977        }
978    }
979    removedCommands.clear();
980
981    // insert command at the right place according to its time stamp
982    ALOGV("inserting command: %d at index %d, num commands %d",
983            command->mCommand, (int)i+1, mAudioCommands.size());
984    mAudioCommands.insertAt(command, i + 1);
985}
986
987void AudioPolicyService::AudioCommandThread::exit()
988{
989    ALOGV("AudioCommandThread::exit");
990    {
991        AutoMutex _l(mLock);
992        requestExit();
993        mWaitWorkCV.signal();
994    }
995    requestExitAndWait();
996}
997
998void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
999{
1000    snprintf(buffer, size, "   %02d      %06d.%03d  %01u    %p\n",
1001            mCommand,
1002            (int)ns2s(mTime),
1003            (int)ns2ms(mTime)%1000,
1004            mWaitStatus,
1005            mParam);
1006}
1007
1008/******* helpers for the service_ops callbacks defined below *********/
1009void AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
1010                                       const char *keyValuePairs,
1011                                       int delayMs)
1012{
1013    mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs,
1014                                           delayMs);
1015}
1016
1017int AudioPolicyService::setStreamVolume(audio_stream_type_t stream,
1018                                        float volume,
1019                                        audio_io_handle_t output,
1020                                        int delayMs)
1021{
1022    return (int)mAudioCommandThread->volumeCommand((int)stream, volume,
1023                                                   (int)output, delayMs);
1024}
1025
1026int AudioPolicyService::startTone(audio_policy_tone_t tone,
1027                                  audio_stream_type_t stream)
1028{
1029    if (tone != AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION)
1030        ALOGE("startTone: illegal tone requested (%d)", tone);
1031    if (stream != AUDIO_STREAM_VOICE_CALL)
1032        ALOGE("startTone: illegal stream (%d) requested for tone %d", stream,
1033             tone);
1034    mTonePlaybackThread->startToneCommand(ToneGenerator::TONE_SUP_CALL_WAITING,
1035                                          AUDIO_STREAM_VOICE_CALL);
1036    return 0;
1037}
1038
1039int AudioPolicyService::stopTone()
1040{
1041    mTonePlaybackThread->stopToneCommand();
1042    return 0;
1043}
1044
1045int AudioPolicyService::setVoiceVolume(float volume, int delayMs)
1046{
1047    return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
1048}
1049
1050// ----------------------------------------------------------------------------
1051// Audio pre-processing configuration
1052// ----------------------------------------------------------------------------
1053
1054const char *AudioPolicyService::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
1055    MIC_SRC_TAG,
1056    VOICE_UL_SRC_TAG,
1057    VOICE_DL_SRC_TAG,
1058    VOICE_CALL_SRC_TAG,
1059    CAMCORDER_SRC_TAG,
1060    VOICE_REC_SRC_TAG,
1061    VOICE_COMM_SRC_TAG
1062};
1063
1064// returns the audio_source_t enum corresponding to the input source name or
1065// AUDIO_SOURCE_CNT is no match found
1066audio_source_t AudioPolicyService::inputSourceNameToEnum(const char *name)
1067{
1068    int i;
1069    for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
1070        if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
1071            ALOGV("inputSourceNameToEnum found source %s %d", name, i);
1072            break;
1073        }
1074    }
1075    return (audio_source_t)i;
1076}
1077
1078size_t AudioPolicyService::growParamSize(char *param,
1079                                         size_t size,
1080                                         size_t *curSize,
1081                                         size_t *totSize)
1082{
1083    // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
1084    size_t pos = ((*curSize - 1 ) / size + 1) * size;
1085
1086    if (pos + size > *totSize) {
1087        while (pos + size > *totSize) {
1088            *totSize += ((*totSize + 7) / 8) * 4;
1089        }
1090        param = (char *)realloc(param, *totSize);
1091    }
1092    *curSize = pos + size;
1093    return pos;
1094}
1095
1096size_t AudioPolicyService::readParamValue(cnode *node,
1097                                          char *param,
1098                                          size_t *curSize,
1099                                          size_t *totSize)
1100{
1101    if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
1102        size_t pos = growParamSize(param, sizeof(short), curSize, totSize);
1103        *(short *)((char *)param + pos) = (short)atoi(node->value);
1104        ALOGV("readParamValue() reading short %d", *(short *)((char *)param + pos));
1105        return sizeof(short);
1106    } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
1107        size_t pos = growParamSize(param, sizeof(int), curSize, totSize);
1108        *(int *)((char *)param + pos) = atoi(node->value);
1109        ALOGV("readParamValue() reading int %d", *(int *)((char *)param + pos));
1110        return sizeof(int);
1111    } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
1112        size_t pos = growParamSize(param, sizeof(float), curSize, totSize);
1113        *(float *)((char *)param + pos) = (float)atof(node->value);
1114        ALOGV("readParamValue() reading float %f",*(float *)((char *)param + pos));
1115        return sizeof(float);
1116    } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
1117        size_t pos = growParamSize(param, sizeof(bool), curSize, totSize);
1118        if (strncmp(node->value, "false", strlen("false") + 1) == 0) {
1119            *(bool *)((char *)param + pos) = false;
1120        } else {
1121            *(bool *)((char *)param + pos) = true;
1122        }
1123        ALOGV("readParamValue() reading bool %s",*(bool *)((char *)param + pos) ? "true" : "false");
1124        return sizeof(bool);
1125    } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
1126        size_t len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
1127        if (*curSize + len + 1 > *totSize) {
1128            *totSize = *curSize + len + 1;
1129            param = (char *)realloc(param, *totSize);
1130        }
1131        strncpy(param + *curSize, node->value, len);
1132        *curSize += len;
1133        param[*curSize] = '\0';
1134        ALOGV("readParamValue() reading string %s", param + *curSize - len);
1135        return len;
1136    }
1137    ALOGW("readParamValue() unknown param type %s", node->name);
1138    return 0;
1139}
1140
1141effect_param_t *AudioPolicyService::loadEffectParameter(cnode *root)
1142{
1143    cnode *param;
1144    cnode *value;
1145    size_t curSize = sizeof(effect_param_t);
1146    size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
1147    effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
1148
1149    param = config_find(root, PARAM_TAG);
1150    value = config_find(root, VALUE_TAG);
1151    if (param == NULL && value == NULL) {
1152        // try to parse simple parameter form {int int}
1153        param = root->first_child;
1154        if (param) {
1155            // Note: that a pair of random strings is read as 0 0
1156            int *ptr = (int *)fx_param->data;
1157            int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
1158            ALOGW("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
1159            *ptr++ = atoi(param->name);
1160            *ptr = atoi(param->value);
1161            fx_param->psize = sizeof(int);
1162            fx_param->vsize = sizeof(int);
1163            return fx_param;
1164        }
1165    }
1166    if (param == NULL || value == NULL) {
1167        ALOGW("loadEffectParameter() invalid parameter description %s", root->name);
1168        goto error;
1169    }
1170
1171    fx_param->psize = 0;
1172    param = param->first_child;
1173    while (param) {
1174        ALOGV("loadEffectParameter() reading param of type %s", param->name);
1175        size_t size = readParamValue(param, (char *)fx_param, &curSize, &totSize);
1176        if (size == 0) {
1177            goto error;
1178        }
1179        fx_param->psize += size;
1180        param = param->next;
1181    }
1182
1183    // align start of value field on 32 bit boundary
1184    curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
1185
1186    fx_param->vsize = 0;
1187    value = value->first_child;
1188    while (value) {
1189        ALOGV("loadEffectParameter() reading value of type %s", value->name);
1190        size_t size = readParamValue(value, (char *)fx_param, &curSize, &totSize);
1191        if (size == 0) {
1192            goto error;
1193        }
1194        fx_param->vsize += size;
1195        value = value->next;
1196    }
1197
1198    return fx_param;
1199
1200error:
1201    delete fx_param;
1202    return NULL;
1203}
1204
1205void AudioPolicyService::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
1206{
1207    cnode *node = root->first_child;
1208    while (node) {
1209        ALOGV("loadEffectParameters() loading param %s", node->name);
1210        effect_param_t *param = loadEffectParameter(node);
1211        if (param == NULL) {
1212            node = node->next;
1213            continue;
1214        }
1215        params.add(param);
1216        node = node->next;
1217    }
1218}
1219
1220AudioPolicyService::InputSourceDesc *AudioPolicyService::loadInputSource(
1221                                                            cnode *root,
1222                                                            const Vector <EffectDesc *>& effects)
1223{
1224    cnode *node = root->first_child;
1225    if (node == NULL) {
1226        ALOGW("loadInputSource() empty element %s", root->name);
1227        return NULL;
1228    }
1229    InputSourceDesc *source = new InputSourceDesc();
1230    while (node) {
1231        size_t i;
1232        for (i = 0; i < effects.size(); i++) {
1233            if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
1234                ALOGV("loadInputSource() found effect %s in list", node->name);
1235                break;
1236            }
1237        }
1238        if (i == effects.size()) {
1239            ALOGV("loadInputSource() effect %s not in list", node->name);
1240            node = node->next;
1241            continue;
1242        }
1243        EffectDesc *effect = new EffectDesc(*effects[i]);
1244        loadEffectParameters(node, effect->mParams);
1245        ALOGV("loadInputSource() adding effect %s uuid %08x", effect->mName, effect->mUuid.timeLow);
1246        source->mEffects.add(effect);
1247        node = node->next;
1248    }
1249    if (source->mEffects.size() == 0) {
1250        ALOGW("loadInputSource() no valid effects found in source %s", root->name);
1251        delete source;
1252        return NULL;
1253    }
1254    return source;
1255}
1256
1257status_t AudioPolicyService::loadInputSources(cnode *root, const Vector <EffectDesc *>& effects)
1258{
1259    cnode *node = config_find(root, PREPROCESSING_TAG);
1260    if (node == NULL) {
1261        return -ENOENT;
1262    }
1263    node = node->first_child;
1264    while (node) {
1265        audio_source_t source = inputSourceNameToEnum(node->name);
1266        if (source == AUDIO_SOURCE_CNT) {
1267            ALOGW("loadInputSources() invalid input source %s", node->name);
1268            node = node->next;
1269            continue;
1270        }
1271        ALOGV("loadInputSources() loading input source %s", node->name);
1272        InputSourceDesc *desc = loadInputSource(node, effects);
1273        if (desc == NULL) {
1274            node = node->next;
1275            continue;
1276        }
1277        mInputSources.add(source, desc);
1278        node = node->next;
1279    }
1280    return NO_ERROR;
1281}
1282
1283AudioPolicyService::EffectDesc *AudioPolicyService::loadEffect(cnode *root)
1284{
1285    cnode *node = config_find(root, UUID_TAG);
1286    if (node == NULL) {
1287        return NULL;
1288    }
1289    effect_uuid_t uuid;
1290    if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
1291        ALOGW("loadEffect() invalid uuid %s", node->value);
1292        return NULL;
1293    }
1294    EffectDesc *effect = new EffectDesc();
1295    effect->mName = strdup(root->name);
1296    memcpy(&effect->mUuid, &uuid, sizeof(effect_uuid_t));
1297
1298    return effect;
1299}
1300
1301status_t AudioPolicyService::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
1302{
1303    cnode *node = config_find(root, EFFECTS_TAG);
1304    if (node == NULL) {
1305        return -ENOENT;
1306    }
1307    node = node->first_child;
1308    while (node) {
1309        ALOGV("loadEffects() loading effect %s", node->name);
1310        EffectDesc *effect = loadEffect(node);
1311        if (effect == NULL) {
1312            node = node->next;
1313            continue;
1314        }
1315        effects.add(effect);
1316        node = node->next;
1317    }
1318    return NO_ERROR;
1319}
1320
1321status_t AudioPolicyService::loadPreProcessorConfig(const char *path)
1322{
1323    cnode *root;
1324    char *data;
1325
1326    data = (char *)load_file(path, NULL);
1327    if (data == NULL) {
1328        return -ENODEV;
1329    }
1330    root = config_node("", "");
1331    config_load(root, data);
1332
1333    Vector <EffectDesc *> effects;
1334    loadEffects(root, effects);
1335    loadInputSources(root, effects);
1336
1337    config_free(root);
1338    free(root);
1339    free(data);
1340
1341    return NO_ERROR;
1342}
1343
1344/* implementation of the interface to the policy manager */
1345extern "C" {
1346
1347static audio_io_handle_t aps_open_output(void *service,
1348                                             uint32_t *pDevices,
1349                                             uint32_t *pSamplingRate,
1350                                             uint32_t *pFormat,
1351                                             uint32_t *pChannels,
1352                                             uint32_t *pLatencyMs,
1353                                             audio_policy_output_flags_t flags)
1354{
1355    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1356    if (af == NULL) {
1357        ALOGW("%s: could not get AudioFlinger", __func__);
1358        return 0;
1359    }
1360
1361    return af->openOutput(pDevices, pSamplingRate, pFormat, pChannels,
1362                          pLatencyMs, flags);
1363}
1364
1365static audio_io_handle_t aps_open_dup_output(void *service,
1366                                                 audio_io_handle_t output1,
1367                                                 audio_io_handle_t output2)
1368{
1369    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1370    if (af == NULL) {
1371        ALOGW("%s: could not get AudioFlinger", __func__);
1372        return 0;
1373    }
1374    return af->openDuplicateOutput(output1, output2);
1375}
1376
1377static int aps_close_output(void *service, audio_io_handle_t output)
1378{
1379    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1380    if (af == NULL)
1381        return PERMISSION_DENIED;
1382
1383    return af->closeOutput(output);
1384}
1385
1386static int aps_suspend_output(void *service, audio_io_handle_t output)
1387{
1388    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1389    if (af == NULL) {
1390        ALOGW("%s: could not get AudioFlinger", __func__);
1391        return PERMISSION_DENIED;
1392    }
1393
1394    return af->suspendOutput(output);
1395}
1396
1397static int aps_restore_output(void *service, audio_io_handle_t output)
1398{
1399    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1400    if (af == NULL) {
1401        ALOGW("%s: could not get AudioFlinger", __func__);
1402        return PERMISSION_DENIED;
1403    }
1404
1405    return af->restoreOutput(output);
1406}
1407
1408static audio_io_handle_t aps_open_input(void *service,
1409                                            uint32_t *pDevices,
1410                                            uint32_t *pSamplingRate,
1411                                            uint32_t *pFormat,
1412                                            uint32_t *pChannels,
1413                                            uint32_t acoustics)
1414{
1415    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1416    if (af == NULL) {
1417        ALOGW("%s: could not get AudioFlinger", __func__);
1418        return 0;
1419    }
1420
1421    return af->openInput(pDevices, pSamplingRate, pFormat, pChannels,
1422                         acoustics);
1423}
1424
1425static int aps_close_input(void *service, audio_io_handle_t input)
1426{
1427    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1428    if (af == NULL)
1429        return PERMISSION_DENIED;
1430
1431    return af->closeInput(input);
1432}
1433
1434static int aps_set_stream_output(void *service, audio_stream_type_t stream,
1435                                     audio_io_handle_t output)
1436{
1437    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1438    if (af == NULL)
1439        return PERMISSION_DENIED;
1440
1441    return af->setStreamOutput(stream, output);
1442}
1443
1444static int aps_move_effects(void *service, int session,
1445                                audio_io_handle_t src_output,
1446                                audio_io_handle_t dst_output)
1447{
1448    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1449    if (af == NULL)
1450        return PERMISSION_DENIED;
1451
1452    return af->moveEffects(session, (int)src_output, (int)dst_output);
1453}
1454
1455static char * aps_get_parameters(void *service, audio_io_handle_t io_handle,
1456                                     const char *keys)
1457{
1458    String8 result = AudioSystem::getParameters(io_handle, String8(keys));
1459    return strdup(result.string());
1460}
1461
1462static void aps_set_parameters(void *service, audio_io_handle_t io_handle,
1463                                   const char *kv_pairs, int delay_ms)
1464{
1465    AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
1466
1467    audioPolicyService->setParameters(io_handle, kv_pairs, delay_ms);
1468}
1469
1470static int aps_set_stream_volume(void *service, audio_stream_type_t stream,
1471                                     float volume, audio_io_handle_t output,
1472                                     int delay_ms)
1473{
1474    AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
1475
1476    return audioPolicyService->setStreamVolume(stream, volume, output,
1477                                               delay_ms);
1478}
1479
1480static int aps_start_tone(void *service, audio_policy_tone_t tone,
1481                              audio_stream_type_t stream)
1482{
1483    AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
1484
1485    return audioPolicyService->startTone(tone, stream);
1486}
1487
1488static int aps_stop_tone(void *service)
1489{
1490    AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
1491
1492    return audioPolicyService->stopTone();
1493}
1494
1495static int aps_set_voice_volume(void *service, float volume, int delay_ms)
1496{
1497    AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
1498
1499    return audioPolicyService->setVoiceVolume(volume, delay_ms);
1500}
1501
1502}; // extern "C"
1503
1504namespace {
1505    struct audio_policy_service_ops aps_ops = {
1506        open_output           : aps_open_output,
1507        open_duplicate_output : aps_open_dup_output,
1508        close_output          : aps_close_output,
1509        suspend_output        : aps_suspend_output,
1510        restore_output        : aps_restore_output,
1511        open_input            : aps_open_input,
1512        close_input           : aps_close_input,
1513        set_stream_volume     : aps_set_stream_volume,
1514        set_stream_output     : aps_set_stream_output,
1515        set_parameters        : aps_set_parameters,
1516        get_parameters        : aps_get_parameters,
1517        start_tone            : aps_start_tone,
1518        stop_tone             : aps_stop_tone,
1519        set_voice_volume      : aps_set_voice_volume,
1520        move_effects          : aps_move_effects,
1521    };
1522}; // namespace <unnamed>
1523
1524}; // namespace android
1525