AudioPolicyEffects.cpp revision 897a408b3f9c893776d67214257ca6a6bc1751bd
1ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu/*
2ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu * Copyright (C) 2014 The Android Open Source Project
3ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu *
4ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu * Licensed under the Apache License, Version 2.0 (the "License");
5ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu * you may not use this file except in compliance with the License.
6ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu * You may obtain a copy of the License at
7ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu *
8ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu *      http://www.apache.org/licenses/LICENSE-2.0
9ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu *
10ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu * Unless required by applicable law or agreed to in writing, software
11ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu * distributed under the License is distributed on an "AS IS" BASIS,
12ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu * See the License for the specific language governing permissions and
14ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu * limitations under the License.
15ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu */
16ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
17ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#define LOG_TAG "AudioPolicyEffects"
18897a408b3f9c893776d67214257ca6a6bc1751bdEric Laurent//#define LOG_NDEBUG 0
19ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
20ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <stdlib.h>
21ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <stdio.h>
22ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <string.h>
23ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <cutils/misc.h>
24ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <media/AudioEffect.h>
25ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <system/audio.h>
26ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <hardware/audio_effect.h>
27ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <audio_effects/audio_effects_conf.h>
28ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <utils/Vector.h>
29ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <utils/SortedVector.h>
30ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <cutils/config_utils.h>
31ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include "AudioPolicyEffects.h"
32ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include "ServiceUtilities.h"
33ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
34ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liunamespace android {
35ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
36ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// ----------------------------------------------------------------------------
37ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// AudioPolicyEffects Implementation
38ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// ----------------------------------------------------------------------------
39ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
40ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuAudioPolicyEffects::AudioPolicyEffects()
41ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
42ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // load automatic audio effect modules
43ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
44ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
45ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
46ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
47ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
48ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
49ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
50ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
51ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuAudioPolicyEffects::~AudioPolicyEffects()
52ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
53ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    size_t i = 0;
54ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // release audio input processing resources
55ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (i = 0; i < mInputSources.size(); i++) {
56ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        delete mInputSources.valueAt(i);
57ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
58ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    mInputSources.clear();
59ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
60ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (i = 0; i < mInputs.size(); i++) {
61ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        mInputs.valueAt(i)->mEffects.clear();
62ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        delete mInputs.valueAt(i);
63ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
64ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    mInputs.clear();
65ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
66ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // release audio output processing resources
67ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (i = 0; i < mOutputStreams.size(); i++) {
68ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        delete mOutputStreams.valueAt(i);
69ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
70ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    mOutputStreams.clear();
71ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
72ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (i = 0; i < mOutputSessions.size(); i++) {
73ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        mOutputSessions.valueAt(i)->mEffects.clear();
74ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        delete mOutputSessions.valueAt(i);
75ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
76ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    mOutputSessions.clear();
77ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
78ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
79ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
80ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
81ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                             audio_source_t inputSource,
82ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                             int audioSession)
83ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
84ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    status_t status = NO_ERROR;
85ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
86ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // create audio pre processors according to input source
87ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
88ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                    AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
89ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
90ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ssize_t index = mInputSources.indexOfKey(aliasSource);
91ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (index < 0) {
92ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("addInputEffects(): no processing needs to be attached to this source");
93ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return status;
94ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
95ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ssize_t idx = mInputs.indexOfKey(input);
96ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    EffectVector *inputDesc;
97ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (idx < 0) {
98ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        inputDesc = new EffectVector(audioSession);
99ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        mInputs.add(input, inputDesc);
100ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else {
101ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        inputDesc = mInputs.valueAt(idx);
102ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
103ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
104ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
105ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (size_t i = 0; i < effects.size(); i++) {
106ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        EffectDesc *effect = effects[i];
107ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        sp<AudioEffect> fx = new AudioEffect(NULL, &effect->mUuid, -1, 0, 0, audioSession, input);
108ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        status_t status = fx->initCheck();
109ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (status != NO_ERROR && status != ALREADY_EXISTS) {
110ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGW("addInputEffects(): failed to create Fx %s on source %d",
111ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                  effect->mName, (int32_t)aliasSource);
112ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            // fx goes out of scope and strong ref on AudioEffect is released
113ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
114ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
115ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        for (size_t j = 0; j < effect->mParams.size(); j++) {
116ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            fx->setParameter(effect->mParams[j]);
117ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
118ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("addInputEffects(): added Fx %s on source: %d", effect->mName, (int32_t)aliasSource);
119ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        inputDesc->mEffects.add(fx);
120ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
121ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    setProcessorEnabled(inputDesc, true);
122ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
123ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return status;
124ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
125ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
126ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
127ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input)
128ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
129ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    status_t status = NO_ERROR;
130ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
131ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ssize_t index = mInputs.indexOfKey(input);
132ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (index < 0) {
133ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return status;
134ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
135ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    EffectVector *inputDesc = mInputs.valueAt(index);
136ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    setProcessorEnabled(inputDesc, false);
137ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    delete inputDesc;
138ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    mInputs.removeItemsAt(index);
139ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ALOGV("releaseInputEffects(): all effects released");
140ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return status;
141ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
142ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
143ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::queryDefaultInputEffects(int audioSession,
144ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                                      effect_descriptor_t *descriptors,
145ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                                      uint32_t *count)
146ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
147ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    status_t status = NO_ERROR;
148ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
149ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    size_t index;
150ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (index = 0; index < mInputs.size(); index++) {
151ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (mInputs.valueAt(index)->mSessionId == audioSession) {
152ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            break;
153ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
154ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
155ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (index == mInputs.size()) {
156ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        *count = 0;
157ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return BAD_VALUE;
158ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
159ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects;
160ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
161ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (size_t i = 0; i < effects.size(); i++) {
162ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        effect_descriptor_t desc = effects[i]->descriptor();
163ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (i < *count) {
164ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            descriptors[i] = desc;
165ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
166ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
167ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (effects.size() > *count) {
168ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        status = NO_MEMORY;
169ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
170ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    *count = effects.size();
171ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return status;
172ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
173ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
174ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
175ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::queryDefaultOutputSessionEffects(int audioSession,
176ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                         effect_descriptor_t *descriptors,
177ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                         uint32_t *count)
178ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
179ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    status_t status = NO_ERROR;
180ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
181ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    size_t index;
182ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (index = 0; index < mOutputSessions.size(); index++) {
183ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
184ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            break;
185ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
186ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
187ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (index == mOutputSessions.size()) {
188ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        *count = 0;
189ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return BAD_VALUE;
190ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
191ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
192ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
193ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (size_t i = 0; i < effects.size(); i++) {
194ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        effect_descriptor_t desc = effects[i]->descriptor();
195ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (i < *count) {
196ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            descriptors[i] = desc;
197ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
198ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
199ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (effects.size() > *count) {
200ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        status = NO_MEMORY;
201ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
202ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    *count = effects.size();
203ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return status;
204ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
205ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
206ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
207ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
208ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                         audio_stream_type_t stream,
209ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                         int audioSession)
210ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
211ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    status_t status = NO_ERROR;
212ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
213ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // create audio processors according to stream
214ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ssize_t index = mOutputStreams.indexOfKey(stream);
215ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (index < 0) {
216ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
217ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return NO_ERROR;
218ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
219ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
220ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ssize_t idx = mOutputSessions.indexOfKey(audioSession);
221ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    EffectVector *procDesc;
222ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (idx < 0) {
223ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        procDesc = new EffectVector(audioSession);
224ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        mOutputSessions.add(audioSession, procDesc);
225ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else {
226ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        procDesc = mOutputSessions.valueAt(idx);
227ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
228ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
229ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
230ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (size_t i = 0; i < effects.size(); i++) {
231ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        EffectDesc *effect = effects[i];
232ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        sp<AudioEffect> fx = new AudioEffect(NULL, &effect->mUuid, 0, 0, 0, audioSession, output);
233ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        status_t status = fx->initCheck();
234ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (status != NO_ERROR && status != ALREADY_EXISTS) {
235ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGE("addOutputSessionEffects(): failed to create Fx  %s on session %d",
236ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                  effect->mName, audioSession);
237ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            // fx goes out of scope and strong ref on AudioEffect is released
238ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
239ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
240ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
241ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu              effect->mName, audioSession, (int32_t)stream);
242ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        procDesc->mEffects.add(fx);
243ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
244ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
245ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    setProcessorEnabled(procDesc, true);
246ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
247ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return status;
248ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
249ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
250ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
251ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                         audio_stream_type_t stream,
252ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                         int audioSession)
253ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
254ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    status_t status = NO_ERROR;
255ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    (void) output; // argument not used for now
256ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    (void) stream; // argument not used for now
257ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
258ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ssize_t index = mOutputSessions.indexOfKey(audioSession);
259ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (index < 0) {
260ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
261ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return NO_ERROR;
262ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
263ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
264ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    EffectVector *procDesc = mOutputSessions.valueAt(index);
265ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    setProcessorEnabled(procDesc, false);
266ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    procDesc->mEffects.clear();
267ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    delete procDesc;
268ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    mOutputSessions.removeItemsAt(index);
269ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
270ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu          audioSession);
271ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return status;
272ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
273ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
274ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
275ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuvoid AudioPolicyEffects::setProcessorEnabled(const EffectVector *effectVector, bool enabled)
276ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
277ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    const Vector<sp<AudioEffect> > &fxVector = effectVector->mEffects;
278ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (size_t i = 0; i < fxVector.size(); i++) {
279ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        fxVector.itemAt(i)->setEnabled(enabled);
280ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
281ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
282ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
283ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
284ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// ----------------------------------------------------------------------------
285ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// Audio processing configuration
286ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// ----------------------------------------------------------------------------
287ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
288ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
289ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    MIC_SRC_TAG,
290ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    VOICE_UL_SRC_TAG,
291ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    VOICE_DL_SRC_TAG,
292ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    VOICE_CALL_SRC_TAG,
293ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    CAMCORDER_SRC_TAG,
294ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    VOICE_REC_SRC_TAG,
295ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    VOICE_COMM_SRC_TAG
296ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu};
297ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
298ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// returns the audio_source_t enum corresponding to the input source name or
299ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// AUDIO_SOURCE_CNT is no match found
300ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuaudio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
301ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
302ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    int i;
303ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
304ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
305ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGV("inputSourceNameToEnum found source %s %d", name, i);
306ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            break;
307ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
308ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
309ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return (audio_source_t)i;
310ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
311ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
312ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuconst char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_CNT+1] = {
313ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_DEFAULT_TAG,
314ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_VOICE_CALL_TAG,
315ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_SYSTEM_TAG,
316ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_RING_TAG,
317ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_MUSIC_TAG,
318ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_ALARM_TAG,
319ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_NOTIFICATION_TAG,
320ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_BLUETOOTH_SCO_TAG,
321ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
322ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_DTMF_TAG,
323ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_TTS_TAG
324ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu};
325ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
326ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// returns the audio_stream_t enum corresponding to the output stream name or
327ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// AUDIO_STREAM_CNT is no match found
328ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuaudio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
329ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
330ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    int i;
331ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_CNT; i++) {
332ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
333ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGV("streamNameToEnum found stream %s %d", name, i);
334ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            break;
335ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
336ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
337ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return (audio_stream_type_t)i;
338ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
339ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
340ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// ----------------------------------------------------------------------------
341ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// Audio Effect Config parser
342ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// ----------------------------------------------------------------------------
343ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
344ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liusize_t AudioPolicyEffects::growParamSize(char *param,
345ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                         size_t size,
346ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                         size_t *curSize,
347ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                         size_t *totSize)
348ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
349ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
350ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    size_t pos = ((*curSize - 1 ) / size + 1) * size;
351ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
352ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (pos + size > *totSize) {
353ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        while (pos + size > *totSize) {
354ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            *totSize += ((*totSize + 7) / 8) * 4;
355ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
356ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        param = (char *)realloc(param, *totSize);
357ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
358ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    *curSize = pos + size;
359ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return pos;
360ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
361ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
362ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liusize_t AudioPolicyEffects::readParamValue(cnode *node,
363ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                          char *param,
364ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                          size_t *curSize,
365ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                          size_t *totSize)
366ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
367ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
368ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        size_t pos = growParamSize(param, sizeof(short), curSize, totSize);
369ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        *(short *)((char *)param + pos) = (short)atoi(node->value);
370ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("readParamValue() reading short %d", *(short *)((char *)param + pos));
371ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return sizeof(short);
372ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
373ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        size_t pos = growParamSize(param, sizeof(int), curSize, totSize);
374ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        *(int *)((char *)param + pos) = atoi(node->value);
375ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("readParamValue() reading int %d", *(int *)((char *)param + pos));
376ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return sizeof(int);
377ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
378ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        size_t pos = growParamSize(param, sizeof(float), curSize, totSize);
379ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        *(float *)((char *)param + pos) = (float)atof(node->value);
380ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("readParamValue() reading float %f",*(float *)((char *)param + pos));
381ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return sizeof(float);
382ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
383ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        size_t pos = growParamSize(param, sizeof(bool), curSize, totSize);
384ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (strncmp(node->value, "false", strlen("false") + 1) == 0) {
385ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            *(bool *)((char *)param + pos) = false;
386ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        } else {
387ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            *(bool *)((char *)param + pos) = true;
388ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
389ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("readParamValue() reading bool %s",*(bool *)((char *)param + pos) ? "true" : "false");
390ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return sizeof(bool);
391ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
392ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        size_t len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
393ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (*curSize + len + 1 > *totSize) {
394ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            *totSize = *curSize + len + 1;
395ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            param = (char *)realloc(param, *totSize);
396ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
397ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        strncpy(param + *curSize, node->value, len);
398ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        *curSize += len;
399ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        param[*curSize] = '\0';
400ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("readParamValue() reading string %s", param + *curSize - len);
401ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return len;
402ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
403ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ALOGW("readParamValue() unknown param type %s", node->name);
404ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return 0;
405ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
406ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
407ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liueffect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
408ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
409ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *param;
410ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *value;
411ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    size_t curSize = sizeof(effect_param_t);
412ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
413ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
414ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
415ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    param = config_find(root, PARAM_TAG);
416ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    value = config_find(root, VALUE_TAG);
417ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (param == NULL && value == NULL) {
418ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        // try to parse simple parameter form {int int}
419ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        param = root->first_child;
420ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (param != NULL) {
421ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            // Note: that a pair of random strings is read as 0 0
422ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            int *ptr = (int *)fx_param->data;
423ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
424ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGW("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
425ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            *ptr++ = atoi(param->name);
426ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            *ptr = atoi(param->value);
427ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            fx_param->psize = sizeof(int);
428ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            fx_param->vsize = sizeof(int);
429ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            return fx_param;
430ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
431ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
432ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (param == NULL || value == NULL) {
433ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGW("loadEffectParameter() invalid parameter description %s", root->name);
434ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        goto error;
435ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
436ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
437ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    fx_param->psize = 0;
438ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    param = param->first_child;
439ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (param) {
440ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadEffectParameter() reading param of type %s", param->name);
441ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        size_t size = readParamValue(param, (char *)fx_param, &curSize, &totSize);
442ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (size == 0) {
443ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            goto error;
444ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
445ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        fx_param->psize += size;
446ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        param = param->next;
447ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
448ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
449ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // align start of value field on 32 bit boundary
450ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
451ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
452ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    fx_param->vsize = 0;
453ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    value = value->first_child;
454ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (value) {
455ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadEffectParameter() reading value of type %s", value->name);
456ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        size_t size = readParamValue(value, (char *)fx_param, &curSize, &totSize);
457ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (size == 0) {
458ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            goto error;
459ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
460ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        fx_param->vsize += size;
461ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        value = value->next;
462ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
463ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
464ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return fx_param;
465ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
466ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuerror:
467ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    delete fx_param;
468ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return NULL;
469ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
470ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
471ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuvoid AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
472ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
473ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *node = root->first_child;
474ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (node) {
475ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadEffectParameters() loading param %s", node->name);
476ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        effect_param_t *param = loadEffectParameter(node);
477ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (param == NULL) {
478ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
479ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
480ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
481ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        params.add(param);
482ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        node = node->next;
483ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
484ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
485ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
486ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
487ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuAudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
488ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                                            cnode *root,
489ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                                            const Vector <EffectDesc *>& effects)
490ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
491ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *node = root->first_child;
492ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (node == NULL) {
493ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGW("loadInputSource() empty element %s", root->name);
494ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return NULL;
495ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
496ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    EffectDescVector *desc = new EffectDescVector();
497ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (node) {
498ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        size_t i;
499ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        for (i = 0; i < effects.size(); i++) {
500ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
501ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                ALOGV("loadEffectConfig() found effect %s in list", node->name);
502ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                break;
503ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            }
504ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
505ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (i == effects.size()) {
506ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGV("loadEffectConfig() effect %s not in list", node->name);
507ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
508ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
509ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
510ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        EffectDesc *effect = new EffectDesc(*effects[i]);   // deep copy
511ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        loadEffectParameters(node, effect->mParams);
512ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadEffectConfig() adding effect %s uuid %08x",
513ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu              effect->mName, effect->mUuid.timeLow);
514ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        desc->mEffects.add(effect);
515ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        node = node->next;
516ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
517ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (desc->mEffects.size() == 0) {
518ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
519ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        delete desc;
520ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return NULL;
521ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
522ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return desc;
523ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
524ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
525ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
526ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                                           const Vector <EffectDesc *>& effects)
527ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
528ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *node = config_find(root, PREPROCESSING_TAG);
529ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (node == NULL) {
530ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return -ENOENT;
531ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
532ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    node = node->first_child;
533ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (node) {
534ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        audio_source_t source = inputSourceNameToEnum(node->name);
535ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (source == AUDIO_SOURCE_CNT) {
536ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGW("loadInputSources() invalid input source %s", node->name);
537ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
538ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
539ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
540ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadInputSources() loading input source %s", node->name);
541ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        EffectDescVector *desc = loadEffectConfig(node, effects);
542ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (desc == NULL) {
543ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
544ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
545ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
546ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        mInputSources.add(source, desc);
547ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        node = node->next;
548ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
549ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return NO_ERROR;
550ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
551ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
552ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
553ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                                            const Vector <EffectDesc *>& effects)
554ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
555ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
556ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (node == NULL) {
557ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return -ENOENT;
558ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
559ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    node = node->first_child;
560ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (node) {
561ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        audio_stream_type_t stream = streamNameToEnum(node->name);
562ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (stream == AUDIO_STREAM_CNT) {
563ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
564ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
565ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
566ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
567ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
568ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        EffectDescVector *desc = loadEffectConfig(node, effects);
569ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (desc == NULL) {
570ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
571ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
572ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
573ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        mOutputStreams.add(stream, desc);
574ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        node = node->next;
575ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
576ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return NO_ERROR;
577ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
578ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
579ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuAudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
580ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
581ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *node = config_find(root, UUID_TAG);
582ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (node == NULL) {
583ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return NULL;
584ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
585ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    effect_uuid_t uuid;
586ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
587ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGW("loadEffect() invalid uuid %s", node->value);
588ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return NULL;
589ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
590ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return new EffectDesc(root->name, uuid);
591ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
592ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
593ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
594ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
595ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *node = config_find(root, EFFECTS_TAG);
596ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (node == NULL) {
597ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return -ENOENT;
598ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
599ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    node = node->first_child;
600ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (node) {
601ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadEffects() loading effect %s", node->name);
602ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        EffectDesc *effect = loadEffect(node);
603ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (effect == NULL) {
604ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
605ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
606ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
607ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        effects.add(effect);
608ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        node = node->next;
609ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
610ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return NO_ERROR;
611ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
612ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
613ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
614ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
615ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *root;
616ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    char *data;
617ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
618ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    data = (char *)load_file(path, NULL);
619ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (data == NULL) {
620ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return -ENODEV;
621ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
622ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    root = config_node("", "");
623ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    config_load(root, data);
624ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
625ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    Vector <EffectDesc *> effects;
626ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    loadEffects(root, effects);
627ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    loadInputEffectConfigurations(root, effects);
628ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    loadStreamEffectConfigurations(root, effects);
629ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
630ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    config_free(root);
631ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    free(root);
632ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    free(data);
633ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
634ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return NO_ERROR;
635ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
636ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
637ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
638ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}; // namespace android
639