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