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