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>
234fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard#include <memory>
24ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <cutils/misc.h>
25ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <media/AudioEffect.h>
264fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard#include <media/EffectsConfig.h>
27ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <system/audio.h>
28c2f710f89ec1a3ea8e448bfafcc02b03529cc681Mikhail Naganov#include <system/audio_effects/audio_effects_conf.h>
29ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <utils/Vector.h>
30ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <utils/SortedVector.h>
31ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include <cutils/config_utils.h>
32b643627a557e44b9ab5879cf71e162af2d514ce3Eric Laurent#include <binder/IPCThreadState.h>
33ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include "AudioPolicyEffects.h"
34ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu#include "ServiceUtilities.h"
35ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
36ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liunamespace android {
37ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
38ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// ----------------------------------------------------------------------------
39ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// AudioPolicyEffects Implementation
40ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// ----------------------------------------------------------------------------
41ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
42ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuAudioPolicyEffects::AudioPolicyEffects()
43ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
444fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard    status_t loadResult = loadAudioEffectXmlConfig();
454fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard    if (loadResult < 0) {
464fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard        ALOGW("Failed to load XML effect configuration, fallback to .conf");
474fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard        // load automatic audio effect modules
484fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard        if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
494fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard            loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
504fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard        } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
514fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard            loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
524fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard        }
534fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard    } else if (loadResult > 0) {
544fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard        ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
55ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
56ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
57ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
58ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
59ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuAudioPolicyEffects::~AudioPolicyEffects()
60ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
61ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    size_t i = 0;
62ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // release audio input processing resources
63ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (i = 0; i < mInputSources.size(); i++) {
64ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        delete mInputSources.valueAt(i);
65ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
66ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    mInputSources.clear();
67ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
68fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    for (i = 0; i < mInputSessions.size(); i++) {
69fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent        mInputSessions.valueAt(i)->mEffects.clear();
70fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent        delete mInputSessions.valueAt(i);
71ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
72fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    mInputSessions.clear();
73ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
74ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // release audio output processing resources
75ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (i = 0; i < mOutputStreams.size(); i++) {
76ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        delete mOutputStreams.valueAt(i);
77ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
78ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    mOutputStreams.clear();
79ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
80ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (i = 0; i < mOutputSessions.size(); i++) {
81ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        mOutputSessions.valueAt(i)->mEffects.clear();
82ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        delete mOutputSessions.valueAt(i);
83ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
84ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    mOutputSessions.clear();
85ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
86ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
87ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
88ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
89ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                             audio_source_t inputSource,
90fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent                             audio_session_t audioSession)
91ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
92ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    status_t status = NO_ERROR;
93ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
94ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // create audio pre processors according to input source
95ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
96ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                    AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
97ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
988b1e80bf1e9f214feea219cfe981ba533b806003Eric Laurent    Mutex::Autolock _l(mLock);
99ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ssize_t index = mInputSources.indexOfKey(aliasSource);
100ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (index < 0) {
101ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("addInputEffects(): no processing needs to be attached to this source");
102ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return status;
103ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
104fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    ssize_t idx = mInputSessions.indexOfKey(audioSession);
105fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    EffectVector *sessionDesc;
106ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (idx < 0) {
107fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent        sessionDesc = new EffectVector(audioSession);
108fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent        mInputSessions.add(audioSession, sessionDesc);
109ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else {
110890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu        // EffectVector is existing and we just need to increase ref count
111fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent        sessionDesc = mInputSessions.valueAt(idx);
112ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
113fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    sessionDesc->mRefCount++;
114890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu
115fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
116fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    if (sessionDesc->mRefCount == 1) {
117b643627a557e44b9ab5879cf71e162af2d514ce3Eric Laurent        int64_t token = IPCThreadState::self()->clearCallingIdentity();
1187de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent        Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
1197de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent        for (size_t i = 0; i < effects.size(); i++) {
1207de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            EffectDesc *effect = effects[i];
121be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov            sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, -1, 0,
122be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov                                                 0, audioSession, input);
1237de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            status_t status = fx->initCheck();
1247de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            if (status != NO_ERROR && status != ALREADY_EXISTS) {
1257de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent                ALOGW("addInputEffects(): failed to create Fx %s on source %d",
1267de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent                      effect->mName, (int32_t)aliasSource);
1277de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent                // fx goes out of scope and strong ref on AudioEffect is released
1287de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent                continue;
1297de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            }
1307de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            for (size_t j = 0; j < effect->mParams.size(); j++) {
1317de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent                fx->setParameter(effect->mParams[j]);
1327de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            }
1337de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            ALOGV("addInputEffects(): added Fx %s on source: %d",
134ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                  effect->mName, (int32_t)aliasSource);
135fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent            sessionDesc->mEffects.add(fx);
136ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
137fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent        sessionDesc->setProcessorEnabled(true);
138b643627a557e44b9ab5879cf71e162af2d514ce3Eric Laurent        IPCThreadState::self()->restoreCallingIdentity(token);
139ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
140ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return status;
141ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
142ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
143ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
144fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurentstatus_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
145fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent                                                 audio_session_t audioSession)
146ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
147ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    status_t status = NO_ERROR;
148ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
1498b1e80bf1e9f214feea219cfe981ba533b806003Eric Laurent    Mutex::Autolock _l(mLock);
150fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    ssize_t index = mInputSessions.indexOfKey(audioSession);
151ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (index < 0) {
152ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return status;
153ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
154fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    EffectVector *sessionDesc = mInputSessions.valueAt(index);
155fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    sessionDesc->mRefCount--;
156fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
157fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    if (sessionDesc->mRefCount == 0) {
158fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent        sessionDesc->setProcessorEnabled(false);
159fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent        delete sessionDesc;
160fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent        mInputSessions.removeItemsAt(index);
161890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu        ALOGV("releaseInputEffects(): all effects released");
162890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu    }
163ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return status;
164ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
165ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
166fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurentstatus_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
167ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                                      effect_descriptor_t *descriptors,
168ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                                      uint32_t *count)
169ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
170ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    status_t status = NO_ERROR;
171ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
1728b1e80bf1e9f214feea219cfe981ba533b806003Eric Laurent    Mutex::Autolock _l(mLock);
173ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    size_t index;
174fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    for (index = 0; index < mInputSessions.size(); index++) {
175fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent        if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
176ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            break;
177ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
178ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
179fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    if (index == mInputSessions.size()) {
180ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        *count = 0;
181ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return BAD_VALUE;
182ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
183fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent    Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
184ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
185ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (size_t i = 0; i < effects.size(); i++) {
186ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        effect_descriptor_t desc = effects[i]->descriptor();
187ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (i < *count) {
188ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            descriptors[i] = desc;
189ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
190ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
191ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (effects.size() > *count) {
192ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        status = NO_MEMORY;
193ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
194ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    *count = effects.size();
195ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return status;
196ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
197ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
198ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
199fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurentstatus_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
200ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                         effect_descriptor_t *descriptors,
201ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                         uint32_t *count)
202ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
203ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    status_t status = NO_ERROR;
204ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
2058b1e80bf1e9f214feea219cfe981ba533b806003Eric Laurent    Mutex::Autolock _l(mLock);
206ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    size_t index;
207ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (index = 0; index < mOutputSessions.size(); index++) {
208ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
209ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            break;
210ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
211ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
212ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (index == mOutputSessions.size()) {
213ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        *count = 0;
214ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return BAD_VALUE;
215ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
216ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
217ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
218ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (size_t i = 0; i < effects.size(); i++) {
219ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        effect_descriptor_t desc = effects[i]->descriptor();
220ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (i < *count) {
221ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            descriptors[i] = desc;
222ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
223ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
224ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (effects.size() > *count) {
225ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        status = NO_MEMORY;
226ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
227ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    *count = effects.size();
228ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return status;
229ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
230ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
231ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
232ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
233ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                         audio_stream_type_t stream,
234fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent                         audio_session_t audioSession)
235ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
236ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    status_t status = NO_ERROR;
237ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
2388b1e80bf1e9f214feea219cfe981ba533b806003Eric Laurent    Mutex::Autolock _l(mLock);
239ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // create audio processors according to stream
240223fd5c9738e9665e495904d37d4632414b68c1eEric Laurent    // FIXME: should we have specific post processing settings for internal streams?
241223fd5c9738e9665e495904d37d4632414b68c1eEric Laurent    // default to media for now.
242223fd5c9738e9665e495904d37d4632414b68c1eEric Laurent    if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
243223fd5c9738e9665e495904d37d4632414b68c1eEric Laurent        stream = AUDIO_STREAM_MUSIC;
244223fd5c9738e9665e495904d37d4632414b68c1eEric Laurent    }
245ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ssize_t index = mOutputStreams.indexOfKey(stream);
246ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (index < 0) {
247ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
248ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return NO_ERROR;
249ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
250ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
251ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ssize_t idx = mOutputSessions.indexOfKey(audioSession);
252ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    EffectVector *procDesc;
253ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (idx < 0) {
254ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        procDesc = new EffectVector(audioSession);
255ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        mOutputSessions.add(audioSession, procDesc);
256ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else {
257890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu        // EffectVector is existing and we just need to increase ref count
258ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        procDesc = mOutputSessions.valueAt(idx);
259ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
260890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu    procDesc->mRefCount++;
261890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu
2627de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent    ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
2637de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent          audioSession, procDesc->mRefCount);
2647de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent    if (procDesc->mRefCount == 1) {
265b643627a557e44b9ab5879cf71e162af2d514ce3Eric Laurent        // make sure effects are associated to audio server even if we are executing a binder call
266b643627a557e44b9ab5879cf71e162af2d514ce3Eric Laurent        int64_t token = IPCThreadState::self()->clearCallingIdentity();
2677de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent        Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
2687de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent        for (size_t i = 0; i < effects.size(); i++) {
2697de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            EffectDesc *effect = effects[i];
270be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov            sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, 0, 0, 0,
2717de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent                                                 audioSession, output);
2727de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            status_t status = fx->initCheck();
2737de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            if (status != NO_ERROR && status != ALREADY_EXISTS) {
2747de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent                ALOGE("addOutputSessionEffects(): failed to create Fx  %s on session %d",
2757de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent                      effect->mName, audioSession);
2767de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent                // fx goes out of scope and strong ref on AudioEffect is released
2777de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent                continue;
2787de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            }
2797de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
2807de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent                  effect->mName, audioSession, (int32_t)stream);
2817de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent            procDesc->mEffects.add(fx);
282ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
283ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
2847de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent        procDesc->setProcessorEnabled(true);
285b643627a557e44b9ab5879cf71e162af2d514ce3Eric Laurent        IPCThreadState::self()->restoreCallingIdentity(token);
2867de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent    }
287ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return status;
288ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
289ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
290ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
291ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                         audio_stream_type_t stream,
292fb66dd9f95a1168698f072c4e5c2a2cf8c49a80fEric Laurent                         audio_session_t audioSession)
293ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
294ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    status_t status = NO_ERROR;
295ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    (void) output; // argument not used for now
296ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    (void) stream; // argument not used for now
297ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
2988b1e80bf1e9f214feea219cfe981ba533b806003Eric Laurent    Mutex::Autolock _l(mLock);
299ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    ssize_t index = mOutputSessions.indexOfKey(audioSession);
300ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (index < 0) {
301ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
302ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return NO_ERROR;
303ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
304ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
305ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    EffectVector *procDesc = mOutputSessions.valueAt(index);
306890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu    procDesc->mRefCount--;
3077de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent    ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
3087de5ac1f067ec61f7ea424d5534cfd40987b11faEric Laurent          audioSession, procDesc->mRefCount);
309890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu    if (procDesc->mRefCount == 0) {
3108b1e80bf1e9f214feea219cfe981ba533b806003Eric Laurent        procDesc->setProcessorEnabled(false);
311890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu        procDesc->mEffects.clear();
312890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu        delete procDesc;
313890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu        mOutputSessions.removeItemsAt(index);
314890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu        ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
315890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu              audioSession);
316890a5637b3e3eb197fd2c7f5deec816c7feb13fcbryant_liu    }
317ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return status;
318ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
319ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
320ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
3218b1e80bf1e9f214feea219cfe981ba533b806003Eric Laurentvoid AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
322ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
3238b1e80bf1e9f214feea219cfe981ba533b806003Eric Laurent    for (size_t i = 0; i < mEffects.size(); i++) {
3248b1e80bf1e9f214feea219cfe981ba533b806003Eric Laurent        mEffects.itemAt(i)->setEnabled(enabled);
325ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
326ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
327ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
328ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
329ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// ----------------------------------------------------------------------------
330ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// Audio processing configuration
331ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// ----------------------------------------------------------------------------
332ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
333ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
334ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    MIC_SRC_TAG,
335ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    VOICE_UL_SRC_TAG,
336ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    VOICE_DL_SRC_TAG,
337ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    VOICE_CALL_SRC_TAG,
338ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    CAMCORDER_SRC_TAG,
339ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    VOICE_REC_SRC_TAG,
3408a397d583a4f4cf24ad88facaf2fd33990cfb811rago    VOICE_COMM_SRC_TAG,
3418a397d583a4f4cf24ad88facaf2fd33990cfb811rago    UNPROCESSED_SRC_TAG
342ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu};
343ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
344ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// returns the audio_source_t enum corresponding to the input source name or
345ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// AUDIO_SOURCE_CNT is no match found
3468b1e80bf1e9f214feea219cfe981ba533b806003Eric Laurent/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
347ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
348ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    int i;
349ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
350ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
351ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGV("inputSourceNameToEnum found source %s %d", name, i);
352ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            break;
353ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
354ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
355ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return (audio_source_t)i;
356ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
357ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
358223fd5c9738e9665e495904d37d4632414b68c1eEric Laurentconst char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
359ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_DEFAULT_TAG,
360ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_VOICE_CALL_TAG,
361ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_SYSTEM_TAG,
362ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_RING_TAG,
363ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_MUSIC_TAG,
364ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_ALARM_TAG,
365ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_NOTIFICATION_TAG,
366ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_BLUETOOTH_SCO_TAG,
367ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
368ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_DTMF_TAG,
369ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    AUDIO_STREAM_TTS_TAG
370ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu};
371ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
372ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// returns the audio_stream_t enum corresponding to the output stream name or
373223fd5c9738e9665e495904d37d4632414b68c1eEric Laurent// AUDIO_STREAM_PUBLIC_CNT is no match found
374ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuaudio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
375ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
376ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    int i;
377223fd5c9738e9665e495904d37d4632414b68c1eEric Laurent    for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
378ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
379ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGV("streamNameToEnum found stream %s %d", name, i);
380ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            break;
381ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
382ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
383ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return (audio_stream_type_t)i;
384ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
385ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
386ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// ----------------------------------------------------------------------------
387ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// Audio Effect Config parser
388ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu// ----------------------------------------------------------------------------
389ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
390138ed1796f8c8edd318488911a9b056877191778Eric Laurentsize_t AudioPolicyEffects::growParamSize(char **param,
391ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                         size_t size,
392ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                         size_t *curSize,
393ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                         size_t *totSize)
394ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
395ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
396ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    size_t pos = ((*curSize - 1 ) / size + 1) * size;
397ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
398ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (pos + size > *totSize) {
399ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        while (pos + size > *totSize) {
400ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            *totSize += ((*totSize + 7) / 8) * 4;
401ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
40231225688b7b09ad15f5b1fb8ab2868cecc551f15George Burgess IV        char *newParam = (char *)realloc(*param, *totSize);
40331225688b7b09ad15f5b1fb8ab2868cecc551f15George Burgess IV        if (newParam == NULL) {
404138ed1796f8c8edd318488911a9b056877191778Eric Laurent            ALOGE("%s realloc error for size %zu", __func__, *totSize);
405138ed1796f8c8edd318488911a9b056877191778Eric Laurent            return 0;
406138ed1796f8c8edd318488911a9b056877191778Eric Laurent        }
40731225688b7b09ad15f5b1fb8ab2868cecc551f15George Burgess IV        *param = newParam;
408ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
409ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    *curSize = pos + size;
410ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return pos;
411ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
412ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
413138ed1796f8c8edd318488911a9b056877191778Eric Laurent
414ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liusize_t AudioPolicyEffects::readParamValue(cnode *node,
415138ed1796f8c8edd318488911a9b056877191778Eric Laurent                                          char **param,
416ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                          size_t *curSize,
417ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                          size_t *totSize)
418ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
419138ed1796f8c8edd318488911a9b056877191778Eric Laurent    size_t len = 0;
420138ed1796f8c8edd318488911a9b056877191778Eric Laurent    size_t pos;
421138ed1796f8c8edd318488911a9b056877191778Eric Laurent
422ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
423138ed1796f8c8edd318488911a9b056877191778Eric Laurent        pos = growParamSize(param, sizeof(short), curSize, totSize);
424138ed1796f8c8edd318488911a9b056877191778Eric Laurent        if (pos == 0) {
425138ed1796f8c8edd318488911a9b056877191778Eric Laurent            goto exit;
426138ed1796f8c8edd318488911a9b056877191778Eric Laurent        }
427138ed1796f8c8edd318488911a9b056877191778Eric Laurent        *(short *)(*param + pos) = (short)atoi(node->value);
428138ed1796f8c8edd318488911a9b056877191778Eric Laurent        ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
429138ed1796f8c8edd318488911a9b056877191778Eric Laurent        len = sizeof(short);
430ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
431138ed1796f8c8edd318488911a9b056877191778Eric Laurent        pos = growParamSize(param, sizeof(int), curSize, totSize);
432138ed1796f8c8edd318488911a9b056877191778Eric Laurent        if (pos == 0) {
433138ed1796f8c8edd318488911a9b056877191778Eric Laurent            goto exit;
434138ed1796f8c8edd318488911a9b056877191778Eric Laurent        }
435138ed1796f8c8edd318488911a9b056877191778Eric Laurent        *(int *)(*param + pos) = atoi(node->value);
436138ed1796f8c8edd318488911a9b056877191778Eric Laurent        ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
437138ed1796f8c8edd318488911a9b056877191778Eric Laurent        len = sizeof(int);
438ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
439138ed1796f8c8edd318488911a9b056877191778Eric Laurent        pos = growParamSize(param, sizeof(float), curSize, totSize);
440138ed1796f8c8edd318488911a9b056877191778Eric Laurent        if (pos == 0) {
441138ed1796f8c8edd318488911a9b056877191778Eric Laurent            goto exit;
442138ed1796f8c8edd318488911a9b056877191778Eric Laurent        }
443138ed1796f8c8edd318488911a9b056877191778Eric Laurent        *(float *)(*param + pos) = (float)atof(node->value);
444138ed1796f8c8edd318488911a9b056877191778Eric Laurent        ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
445138ed1796f8c8edd318488911a9b056877191778Eric Laurent        len = sizeof(float);
446ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
447138ed1796f8c8edd318488911a9b056877191778Eric Laurent        pos = growParamSize(param, sizeof(bool), curSize, totSize);
448138ed1796f8c8edd318488911a9b056877191778Eric Laurent        if (pos == 0) {
449138ed1796f8c8edd318488911a9b056877191778Eric Laurent            goto exit;
450138ed1796f8c8edd318488911a9b056877191778Eric Laurent        }
451138ed1796f8c8edd318488911a9b056877191778Eric Laurent        if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
452138ed1796f8c8edd318488911a9b056877191778Eric Laurent            *(bool *)(*param + pos) = true;
453ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        } else {
454138ed1796f8c8edd318488911a9b056877191778Eric Laurent            *(bool *)(*param + pos) = false;
455ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
456138ed1796f8c8edd318488911a9b056877191778Eric Laurent        ALOGV("readParamValue() reading bool %s",
457138ed1796f8c8edd318488911a9b056877191778Eric Laurent              *(bool *)(*param + pos) ? "true" : "false");
458138ed1796f8c8edd318488911a9b056877191778Eric Laurent        len = sizeof(bool);
459ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
460138ed1796f8c8edd318488911a9b056877191778Eric Laurent        len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
461ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (*curSize + len + 1 > *totSize) {
462ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            *totSize = *curSize + len + 1;
463138ed1796f8c8edd318488911a9b056877191778Eric Laurent            *param = (char *)realloc(*param, *totSize);
464138ed1796f8c8edd318488911a9b056877191778Eric Laurent            if (*param == NULL) {
465138ed1796f8c8edd318488911a9b056877191778Eric Laurent                len = 0;
466138ed1796f8c8edd318488911a9b056877191778Eric Laurent                ALOGE("%s realloc error for string len %zu", __func__, *totSize);
467138ed1796f8c8edd318488911a9b056877191778Eric Laurent                goto exit;
468138ed1796f8c8edd318488911a9b056877191778Eric Laurent            }
469ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
470138ed1796f8c8edd318488911a9b056877191778Eric Laurent        strncpy(*param + *curSize, node->value, len);
471ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        *curSize += len;
472138ed1796f8c8edd318488911a9b056877191778Eric Laurent        (*param)[*curSize] = '\0';
473138ed1796f8c8edd318488911a9b056877191778Eric Laurent        ALOGV("readParamValue() reading string %s", *param + *curSize - len);
474138ed1796f8c8edd318488911a9b056877191778Eric Laurent    } else {
475138ed1796f8c8edd318488911a9b056877191778Eric Laurent        ALOGW("readParamValue() unknown param type %s", node->name);
476ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
477138ed1796f8c8edd318488911a9b056877191778Eric Laurentexit:
478138ed1796f8c8edd318488911a9b056877191778Eric Laurent    return len;
479ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
480ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
481ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liueffect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
482ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
483ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *param;
484ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *value;
485ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    size_t curSize = sizeof(effect_param_t);
486ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
487ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
488ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
489138ed1796f8c8edd318488911a9b056877191778Eric Laurent    if (fx_param == NULL) {
490138ed1796f8c8edd318488911a9b056877191778Eric Laurent        ALOGE("%s malloc error for effect structure of size %zu",
491138ed1796f8c8edd318488911a9b056877191778Eric Laurent              __func__, totSize);
492138ed1796f8c8edd318488911a9b056877191778Eric Laurent        return NULL;
493138ed1796f8c8edd318488911a9b056877191778Eric Laurent    }
494138ed1796f8c8edd318488911a9b056877191778Eric Laurent
495ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    param = config_find(root, PARAM_TAG);
496ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    value = config_find(root, VALUE_TAG);
497ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (param == NULL && value == NULL) {
498ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        // try to parse simple parameter form {int int}
499ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        param = root->first_child;
500ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (param != NULL) {
501ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            // Note: that a pair of random strings is read as 0 0
502ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            int *ptr = (int *)fx_param->data;
503138ed1796f8c8edd318488911a9b056877191778Eric Laurent#if LOG_NDEBUG == 0
504ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
505138ed1796f8c8edd318488911a9b056877191778Eric Laurent            ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
506138ed1796f8c8edd318488911a9b056877191778Eric Laurent#endif
507ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            *ptr++ = atoi(param->name);
508ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            *ptr = atoi(param->value);
509ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            fx_param->psize = sizeof(int);
510ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            fx_param->vsize = sizeof(int);
511ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            return fx_param;
512ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
513ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
514ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (param == NULL || value == NULL) {
515138ed1796f8c8edd318488911a9b056877191778Eric Laurent        ALOGW("loadEffectParameter() invalid parameter description %s",
516138ed1796f8c8edd318488911a9b056877191778Eric Laurent              root->name);
517ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        goto error;
518ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
519ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
520ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    fx_param->psize = 0;
521ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    param = param->first_child;
522ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (param) {
523ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadEffectParameter() reading param of type %s", param->name);
524138ed1796f8c8edd318488911a9b056877191778Eric Laurent        size_t size =
525138ed1796f8c8edd318488911a9b056877191778Eric Laurent                readParamValue(param, (char **)&fx_param, &curSize, &totSize);
526ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (size == 0) {
527ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            goto error;
528ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
529ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        fx_param->psize += size;
530ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        param = param->next;
531ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
532ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
533ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    // align start of value field on 32 bit boundary
534ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
535ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
536ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    fx_param->vsize = 0;
537ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    value = value->first_child;
538ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (value) {
539ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadEffectParameter() reading value of type %s", value->name);
540138ed1796f8c8edd318488911a9b056877191778Eric Laurent        size_t size =
541138ed1796f8c8edd318488911a9b056877191778Eric Laurent                readParamValue(value, (char **)&fx_param, &curSize, &totSize);
542ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (size == 0) {
543ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            goto error;
544ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
545ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        fx_param->vsize += size;
546ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        value = value->next;
547ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
548ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
549ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return fx_param;
550ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
551ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuerror:
552138ed1796f8c8edd318488911a9b056877191778Eric Laurent    free(fx_param);
553ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return NULL;
554ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
555ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
556ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuvoid AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
557ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
558ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *node = root->first_child;
559ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (node) {
560ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadEffectParameters() loading param %s", node->name);
561ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        effect_param_t *param = loadEffectParameter(node);
562138ed1796f8c8edd318488911a9b056877191778Eric Laurent        if (param != NULL) {
563138ed1796f8c8edd318488911a9b056877191778Eric Laurent            params.add(param);
564ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
565ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        node = node->next;
566ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
567ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
568ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
569ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
570ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuAudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
571ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                                            cnode *root,
572ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                                            const Vector <EffectDesc *>& effects)
573ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
574ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *node = root->first_child;
575ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (node == NULL) {
576ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGW("loadInputSource() empty element %s", root->name);
577ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return NULL;
578ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
579ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    EffectDescVector *desc = new EffectDescVector();
580ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (node) {
581ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        size_t i;
582138ed1796f8c8edd318488911a9b056877191778Eric Laurent
583ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        for (i = 0; i < effects.size(); i++) {
584ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
585ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                ALOGV("loadEffectConfig() found effect %s in list", node->name);
586ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                break;
587ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            }
588ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
589ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (i == effects.size()) {
590ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGV("loadEffectConfig() effect %s not in list", node->name);
591ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
592ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
593ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
594ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        EffectDesc *effect = new EffectDesc(*effects[i]);   // deep copy
595ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        loadEffectParameters(node, effect->mParams);
596ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadEffectConfig() adding effect %s uuid %08x",
597ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu              effect->mName, effect->mUuid.timeLow);
598ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        desc->mEffects.add(effect);
599ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        node = node->next;
600ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
601ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (desc->mEffects.size() == 0) {
602ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
603ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        delete desc;
604ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return NULL;
605ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
606ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return desc;
607ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
608ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
609ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
610ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                                           const Vector <EffectDesc *>& effects)
611ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
612ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *node = config_find(root, PREPROCESSING_TAG);
613ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (node == NULL) {
614ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return -ENOENT;
615ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
616ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    node = node->first_child;
617ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (node) {
618ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        audio_source_t source = inputSourceNameToEnum(node->name);
619ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (source == AUDIO_SOURCE_CNT) {
620ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGW("loadInputSources() invalid input source %s", node->name);
621ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
622ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
623ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
624ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadInputSources() loading input source %s", node->name);
625ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        EffectDescVector *desc = loadEffectConfig(node, effects);
626ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (desc == NULL) {
627ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
628ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
629ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
630ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        mInputSources.add(source, desc);
631ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        node = node->next;
632ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
633ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return NO_ERROR;
634ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
635ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
636ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
637ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu                                                            const Vector <EffectDesc *>& effects)
638ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
639ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
640ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (node == NULL) {
641ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return -ENOENT;
642ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
643ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    node = node->first_child;
644ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (node) {
645ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        audio_stream_type_t stream = streamNameToEnum(node->name);
646223fd5c9738e9665e495904d37d4632414b68c1eEric Laurent        if (stream == AUDIO_STREAM_PUBLIC_CNT) {
647ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
648ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
649ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
650ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
651ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
652ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        EffectDescVector *desc = loadEffectConfig(node, effects);
653ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (desc == NULL) {
654ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
655ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
656ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
657ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        mOutputStreams.add(stream, desc);
658ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        node = node->next;
659ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
660ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return NO_ERROR;
661ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
662ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
663ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liuAudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
664ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
665ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *node = config_find(root, UUID_TAG);
666ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (node == NULL) {
667ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return NULL;
668ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
669ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    effect_uuid_t uuid;
670ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
671ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGW("loadEffect() invalid uuid %s", node->value);
672ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return NULL;
673ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
674ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return new EffectDesc(root->name, uuid);
675ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
676ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
677ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
678ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
679ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *node = config_find(root, EFFECTS_TAG);
680ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (node == NULL) {
681ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return -ENOENT;
682ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
683ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    node = node->first_child;
684ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    while (node) {
685ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        ALOGV("loadEffects() loading effect %s", node->name);
686ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        EffectDesc *effect = loadEffect(node);
687ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        if (effect == NULL) {
688ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            node = node->next;
689ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu            continue;
690ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        }
691ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        effects.add(effect);
692ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        node = node->next;
693ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
694ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return NO_ERROR;
695ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
696ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
6974fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocardstatus_t AudioPolicyEffects::loadAudioEffectXmlConfig() {
6984fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard    auto result = effectsConfig::parse();
6994fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard    if (result.parsedConfig == nullptr) {
7004fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard        return -ENOENT;
7014fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard    }
7024fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard
7034fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard    auto loadProcessingChain = [](auto& processingChain, auto& streams) {
7044fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard        for (auto& stream : processingChain) {
7054fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard            auto effectDescs = std::make_unique<EffectDescVector>();
7064fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard            for (auto& effect : stream.effects) {
7074fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard                effectDescs->mEffects.add(
7084fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard                        new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
7094fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard            }
7104fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard            streams.add(stream.type, effectDescs.release());
7114fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard        }
7124fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard    };
7134fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard    loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
7144fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard    loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
7154fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard    // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
7164fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard    return result.nbSkippedElement;
7174fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard}
7184fb615c2774c04b4d36d8f9d88dd4aa291296288Kevin Rocard
719ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liustatus_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
720ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu{
721ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    cnode *root;
722ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    char *data;
723ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
724ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    data = (char *)load_file(path, NULL);
725ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    if (data == NULL) {
726ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu        return -ENODEV;
727ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    }
728ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    root = config_node("", "");
729ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    config_load(root, data);
730ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
731ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    Vector <EffectDesc *> effects;
732ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    loadEffects(root, effects);
733ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    loadInputEffectConfigurations(root, effects);
734ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    loadStreamEffectConfigurations(root, effects);
735ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
736182c2f5e48f46c11dbcb5eecb46268dff4ad4797Eric Laurent    for (size_t i = 0; i < effects.size(); i++) {
737182c2f5e48f46c11dbcb5eecb46268dff4ad4797Eric Laurent        delete effects[i];
738182c2f5e48f46c11dbcb5eecb46268dff4ad4797Eric Laurent    }
739182c2f5e48f46c11dbcb5eecb46268dff4ad4797Eric Laurent
740ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    config_free(root);
741ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    free(root);
742ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    free(data);
743ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
744ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu    return NO_ERROR;
745ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu}
746ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
747ba2b43990a7b4f0f2c425cf6cdfc63376a45772cbryant_liu
7481b2a794a27caab3a1320d22b872b04ef73e96555Mikhail Naganov} // namespace android
749