blob: 6586beabcf45ae961bbb14f7ba9fe8da24452962 [file] [log] [blame]
bryant_liuba2b4392014-06-11 16:49:30 +08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "AudioPolicyEffects"
Eric Laurent897a4082014-07-11 16:51:53 -070018//#define LOG_NDEBUG 0
bryant_liuba2b4392014-06-11 16:49:30 +080019
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <cutils/misc.h>
24#include <media/AudioEffect.h>
25#include <system/audio.h>
Mikhail Naganovc2f710f2016-10-17 18:05:36 -070026#include <system/audio_effects/audio_effects_conf.h>
bryant_liuba2b4392014-06-11 16:49:30 +080027#include <utils/Vector.h>
28#include <utils/SortedVector.h>
29#include <cutils/config_utils.h>
30#include "AudioPolicyEffects.h"
31#include "ServiceUtilities.h"
32
33namespace android {
34
35// ----------------------------------------------------------------------------
36// AudioPolicyEffects Implementation
37// ----------------------------------------------------------------------------
38
39AudioPolicyEffects::AudioPolicyEffects()
40{
41 // load automatic audio effect modules
42 if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
43 loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
44 } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
45 loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
46 }
47}
48
49
50AudioPolicyEffects::~AudioPolicyEffects()
51{
52 size_t i = 0;
53 // release audio input processing resources
54 for (i = 0; i < mInputSources.size(); i++) {
55 delete mInputSources.valueAt(i);
56 }
57 mInputSources.clear();
58
Eric Laurentfb66dd92016-01-28 18:32:03 -080059 for (i = 0; i < mInputSessions.size(); i++) {
60 mInputSessions.valueAt(i)->mEffects.clear();
61 delete mInputSessions.valueAt(i);
bryant_liuba2b4392014-06-11 16:49:30 +080062 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080063 mInputSessions.clear();
bryant_liuba2b4392014-06-11 16:49:30 +080064
65 // release audio output processing resources
66 for (i = 0; i < mOutputStreams.size(); i++) {
67 delete mOutputStreams.valueAt(i);
68 }
69 mOutputStreams.clear();
70
71 for (i = 0; i < mOutputSessions.size(); i++) {
72 mOutputSessions.valueAt(i)->mEffects.clear();
73 delete mOutputSessions.valueAt(i);
74 }
75 mOutputSessions.clear();
76}
77
78
79status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
80 audio_source_t inputSource,
Eric Laurentfb66dd92016-01-28 18:32:03 -080081 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +080082{
83 status_t status = NO_ERROR;
84
85 // create audio pre processors according to input source
86 audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
87 AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
88
Eric Laurent8b1e80b2014-10-07 09:08:47 -070089 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +080090 ssize_t index = mInputSources.indexOfKey(aliasSource);
91 if (index < 0) {
92 ALOGV("addInputEffects(): no processing needs to be attached to this source");
93 return status;
94 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080095 ssize_t idx = mInputSessions.indexOfKey(audioSession);
96 EffectVector *sessionDesc;
bryant_liuba2b4392014-06-11 16:49:30 +080097 if (idx < 0) {
Eric Laurentfb66dd92016-01-28 18:32:03 -080098 sessionDesc = new EffectVector(audioSession);
99 mInputSessions.add(audioSession, sessionDesc);
bryant_liuba2b4392014-06-11 16:49:30 +0800100 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800101 // EffectVector is existing and we just need to increase ref count
Eric Laurentfb66dd92016-01-28 18:32:03 -0800102 sessionDesc = mInputSessions.valueAt(idx);
bryant_liuba2b4392014-06-11 16:49:30 +0800103 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800104 sessionDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +0800105
Eric Laurentfb66dd92016-01-28 18:32:03 -0800106 ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
107 if (sessionDesc->mRefCount == 1) {
Eric Laurent7de5ac12014-10-21 09:07:11 -0700108 Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
109 for (size_t i = 0; i < effects.size(); i++) {
110 EffectDesc *effect = effects[i];
Svet Ganovbe71aa22015-04-28 12:06:02 -0700111 sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, -1, 0,
112 0, audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700113 status_t status = fx->initCheck();
114 if (status != NO_ERROR && status != ALREADY_EXISTS) {
115 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
116 effect->mName, (int32_t)aliasSource);
117 // fx goes out of scope and strong ref on AudioEffect is released
118 continue;
119 }
120 for (size_t j = 0; j < effect->mParams.size(); j++) {
121 fx->setParameter(effect->mParams[j]);
122 }
123 ALOGV("addInputEffects(): added Fx %s on source: %d",
bryant_liuba2b4392014-06-11 16:49:30 +0800124 effect->mName, (int32_t)aliasSource);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800125 sessionDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800126 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800127 sessionDesc->setProcessorEnabled(true);
bryant_liuba2b4392014-06-11 16:49:30 +0800128 }
bryant_liuba2b4392014-06-11 16:49:30 +0800129 return status;
130}
131
132
Eric Laurentfb66dd92016-01-28 18:32:03 -0800133status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
134 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800135{
136 status_t status = NO_ERROR;
137
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700138 Mutex::Autolock _l(mLock);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800139 ssize_t index = mInputSessions.indexOfKey(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800140 if (index < 0) {
141 return status;
142 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800143 EffectVector *sessionDesc = mInputSessions.valueAt(index);
144 sessionDesc->mRefCount--;
145 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
146 if (sessionDesc->mRefCount == 0) {
147 sessionDesc->setProcessorEnabled(false);
148 delete sessionDesc;
149 mInputSessions.removeItemsAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800150 ALOGV("releaseInputEffects(): all effects released");
151 }
bryant_liuba2b4392014-06-11 16:49:30 +0800152 return status;
153}
154
Eric Laurentfb66dd92016-01-28 18:32:03 -0800155status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800156 effect_descriptor_t *descriptors,
157 uint32_t *count)
158{
159 status_t status = NO_ERROR;
160
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700161 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800162 size_t index;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800163 for (index = 0; index < mInputSessions.size(); index++) {
164 if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800165 break;
166 }
167 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800168 if (index == mInputSessions.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800169 *count = 0;
170 return BAD_VALUE;
171 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800172 Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800173
174 for (size_t i = 0; i < effects.size(); i++) {
175 effect_descriptor_t desc = effects[i]->descriptor();
176 if (i < *count) {
177 descriptors[i] = desc;
178 }
179 }
180 if (effects.size() > *count) {
181 status = NO_MEMORY;
182 }
183 *count = effects.size();
184 return status;
185}
186
187
Eric Laurentfb66dd92016-01-28 18:32:03 -0800188status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800189 effect_descriptor_t *descriptors,
190 uint32_t *count)
191{
192 status_t status = NO_ERROR;
193
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700194 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800195 size_t index;
196 for (index = 0; index < mOutputSessions.size(); index++) {
197 if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
198 break;
199 }
200 }
201 if (index == mOutputSessions.size()) {
202 *count = 0;
203 return BAD_VALUE;
204 }
205 Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
206
207 for (size_t i = 0; i < effects.size(); i++) {
208 effect_descriptor_t desc = effects[i]->descriptor();
209 if (i < *count) {
210 descriptors[i] = desc;
211 }
212 }
213 if (effects.size() > *count) {
214 status = NO_MEMORY;
215 }
216 *count = effects.size();
217 return status;
218}
219
220
221status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
222 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800223 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800224{
225 status_t status = NO_ERROR;
226
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700227 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800228 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800229 // FIXME: should we have specific post processing settings for internal streams?
230 // default to media for now.
231 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
232 stream = AUDIO_STREAM_MUSIC;
233 }
bryant_liuba2b4392014-06-11 16:49:30 +0800234 ssize_t index = mOutputStreams.indexOfKey(stream);
235 if (index < 0) {
236 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
237 return NO_ERROR;
238 }
239
240 ssize_t idx = mOutputSessions.indexOfKey(audioSession);
241 EffectVector *procDesc;
242 if (idx < 0) {
243 procDesc = new EffectVector(audioSession);
244 mOutputSessions.add(audioSession, procDesc);
245 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800246 // EffectVector is existing and we just need to increase ref count
bryant_liuba2b4392014-06-11 16:49:30 +0800247 procDesc = mOutputSessions.valueAt(idx);
248 }
bryant_liu890a5632014-08-20 18:06:13 +0800249 procDesc->mRefCount++;
250
Eric Laurent7de5ac12014-10-21 09:07:11 -0700251 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
252 audioSession, procDesc->mRefCount);
253 if (procDesc->mRefCount == 1) {
254 Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
255 for (size_t i = 0; i < effects.size(); i++) {
256 EffectDesc *effect = effects[i];
Svet Ganovbe71aa22015-04-28 12:06:02 -0700257 sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, 0, 0, 0,
Eric Laurent7de5ac12014-10-21 09:07:11 -0700258 audioSession, output);
259 status_t status = fx->initCheck();
260 if (status != NO_ERROR && status != ALREADY_EXISTS) {
261 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
262 effect->mName, audioSession);
263 // fx goes out of scope and strong ref on AudioEffect is released
264 continue;
265 }
266 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
267 effect->mName, audioSession, (int32_t)stream);
268 procDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800269 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700270
271 procDesc->setProcessorEnabled(true);
bryant_liuba2b4392014-06-11 16:49:30 +0800272 }
bryant_liuba2b4392014-06-11 16:49:30 +0800273 return status;
274}
275
276status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
277 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800278 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800279{
280 status_t status = NO_ERROR;
281 (void) output; // argument not used for now
282 (void) stream; // argument not used for now
283
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700284 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800285 ssize_t index = mOutputSessions.indexOfKey(audioSession);
286 if (index < 0) {
287 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
288 return NO_ERROR;
289 }
290
291 EffectVector *procDesc = mOutputSessions.valueAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800292 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700293 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
294 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800295 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700296 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800297 procDesc->mEffects.clear();
298 delete procDesc;
299 mOutputSessions.removeItemsAt(index);
300 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
301 audioSession);
302 }
bryant_liuba2b4392014-06-11 16:49:30 +0800303 return status;
304}
305
306
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700307void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800308{
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700309 for (size_t i = 0; i < mEffects.size(); i++) {
310 mEffects.itemAt(i)->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800311 }
312}
313
314
315// ----------------------------------------------------------------------------
316// Audio processing configuration
317// ----------------------------------------------------------------------------
318
319/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
320 MIC_SRC_TAG,
321 VOICE_UL_SRC_TAG,
322 VOICE_DL_SRC_TAG,
323 VOICE_CALL_SRC_TAG,
324 CAMCORDER_SRC_TAG,
325 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800326 VOICE_COMM_SRC_TAG,
327 UNPROCESSED_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800328};
329
330// returns the audio_source_t enum corresponding to the input source name or
331// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700332/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800333{
334 int i;
335 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
336 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
337 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
338 break;
339 }
340 }
341 return (audio_source_t)i;
342}
343
Eric Laurent223fd5c2014-11-11 13:43:36 -0800344const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800345 AUDIO_STREAM_DEFAULT_TAG,
346 AUDIO_STREAM_VOICE_CALL_TAG,
347 AUDIO_STREAM_SYSTEM_TAG,
348 AUDIO_STREAM_RING_TAG,
349 AUDIO_STREAM_MUSIC_TAG,
350 AUDIO_STREAM_ALARM_TAG,
351 AUDIO_STREAM_NOTIFICATION_TAG,
352 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
353 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
354 AUDIO_STREAM_DTMF_TAG,
355 AUDIO_STREAM_TTS_TAG
356};
357
358// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800359// AUDIO_STREAM_PUBLIC_CNT is no match found
bryant_liuba2b4392014-06-11 16:49:30 +0800360audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
361{
362 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800363 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800364 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
365 ALOGV("streamNameToEnum found stream %s %d", name, i);
366 break;
367 }
368 }
369 return (audio_stream_type_t)i;
370}
371
372// ----------------------------------------------------------------------------
373// Audio Effect Config parser
374// ----------------------------------------------------------------------------
375
Eric Laurent138ed172016-02-10 10:40:44 -0800376size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800377 size_t size,
378 size_t *curSize,
379 size_t *totSize)
380{
381 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
382 size_t pos = ((*curSize - 1 ) / size + 1) * size;
383
384 if (pos + size > *totSize) {
385 while (pos + size > *totSize) {
386 *totSize += ((*totSize + 7) / 8) * 4;
387 }
Eric Laurent138ed172016-02-10 10:40:44 -0800388 *param = (char *)realloc(*param, *totSize);
389 if (*param == NULL) {
390 ALOGE("%s realloc error for size %zu", __func__, *totSize);
391 return 0;
392 }
bryant_liuba2b4392014-06-11 16:49:30 +0800393 }
394 *curSize = pos + size;
395 return pos;
396}
397
Eric Laurent138ed172016-02-10 10:40:44 -0800398
bryant_liuba2b4392014-06-11 16:49:30 +0800399size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800400 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800401 size_t *curSize,
402 size_t *totSize)
403{
Eric Laurent138ed172016-02-10 10:40:44 -0800404 size_t len = 0;
405 size_t pos;
406
bryant_liuba2b4392014-06-11 16:49:30 +0800407 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800408 pos = growParamSize(param, sizeof(short), curSize, totSize);
409 if (pos == 0) {
410 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800411 }
Eric Laurent138ed172016-02-10 10:40:44 -0800412 *(short *)(*param + pos) = (short)atoi(node->value);
413 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
414 len = sizeof(short);
415 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
416 pos = growParamSize(param, sizeof(int), curSize, totSize);
417 if (pos == 0) {
418 goto exit;
419 }
420 *(int *)(*param + pos) = atoi(node->value);
421 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
422 len = sizeof(int);
423 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
424 pos = growParamSize(param, sizeof(float), curSize, totSize);
425 if (pos == 0) {
426 goto exit;
427 }
428 *(float *)(*param + pos) = (float)atof(node->value);
429 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
430 len = sizeof(float);
431 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
432 pos = growParamSize(param, sizeof(bool), curSize, totSize);
433 if (pos == 0) {
434 goto exit;
435 }
436 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
437 *(bool *)(*param + pos) = true;
438 } else {
439 *(bool *)(*param + pos) = false;
440 }
441 ALOGV("readParamValue() reading bool %s",
442 *(bool *)(*param + pos) ? "true" : "false");
443 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800444 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800445 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800446 if (*curSize + len + 1 > *totSize) {
447 *totSize = *curSize + len + 1;
Eric Laurent138ed172016-02-10 10:40:44 -0800448 *param = (char *)realloc(*param, *totSize);
449 if (*param == NULL) {
450 len = 0;
451 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
452 goto exit;
453 }
bryant_liuba2b4392014-06-11 16:49:30 +0800454 }
Eric Laurent138ed172016-02-10 10:40:44 -0800455 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800456 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800457 (*param)[*curSize] = '\0';
458 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
459 } else {
460 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800461 }
Eric Laurent138ed172016-02-10 10:40:44 -0800462exit:
463 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800464}
465
466effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
467{
468 cnode *param;
469 cnode *value;
470 size_t curSize = sizeof(effect_param_t);
471 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
472 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
473
Eric Laurent138ed172016-02-10 10:40:44 -0800474 if (fx_param == NULL) {
475 ALOGE("%s malloc error for effect structure of size %zu",
476 __func__, totSize);
477 return NULL;
478 }
479
bryant_liuba2b4392014-06-11 16:49:30 +0800480 param = config_find(root, PARAM_TAG);
481 value = config_find(root, VALUE_TAG);
482 if (param == NULL && value == NULL) {
483 // try to parse simple parameter form {int int}
484 param = root->first_child;
485 if (param != NULL) {
486 // Note: that a pair of random strings is read as 0 0
487 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800488#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800489 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800490 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
491#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800492 *ptr++ = atoi(param->name);
493 *ptr = atoi(param->value);
494 fx_param->psize = sizeof(int);
495 fx_param->vsize = sizeof(int);
496 return fx_param;
497 }
498 }
499 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800500 ALOGW("loadEffectParameter() invalid parameter description %s",
501 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800502 goto error;
503 }
504
505 fx_param->psize = 0;
506 param = param->first_child;
507 while (param) {
508 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800509 size_t size =
510 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800511 if (size == 0) {
512 goto error;
513 }
514 fx_param->psize += size;
515 param = param->next;
516 }
517
518 // align start of value field on 32 bit boundary
519 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
520
521 fx_param->vsize = 0;
522 value = value->first_child;
523 while (value) {
524 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800525 size_t size =
526 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800527 if (size == 0) {
528 goto error;
529 }
530 fx_param->vsize += size;
531 value = value->next;
532 }
533
534 return fx_param;
535
536error:
Eric Laurent138ed172016-02-10 10:40:44 -0800537 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800538 return NULL;
539}
540
541void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
542{
543 cnode *node = root->first_child;
544 while (node) {
545 ALOGV("loadEffectParameters() loading param %s", node->name);
546 effect_param_t *param = loadEffectParameter(node);
Eric Laurent138ed172016-02-10 10:40:44 -0800547 if (param != NULL) {
548 params.add(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800549 }
bryant_liuba2b4392014-06-11 16:49:30 +0800550 node = node->next;
551 }
552}
553
554
555AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
556 cnode *root,
557 const Vector <EffectDesc *>& effects)
558{
559 cnode *node = root->first_child;
560 if (node == NULL) {
561 ALOGW("loadInputSource() empty element %s", root->name);
562 return NULL;
563 }
564 EffectDescVector *desc = new EffectDescVector();
565 while (node) {
566 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800567
bryant_liuba2b4392014-06-11 16:49:30 +0800568 for (i = 0; i < effects.size(); i++) {
569 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
570 ALOGV("loadEffectConfig() found effect %s in list", node->name);
571 break;
572 }
573 }
574 if (i == effects.size()) {
575 ALOGV("loadEffectConfig() effect %s not in list", node->name);
576 node = node->next;
577 continue;
578 }
579 EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
580 loadEffectParameters(node, effect->mParams);
581 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
582 effect->mName, effect->mUuid.timeLow);
583 desc->mEffects.add(effect);
584 node = node->next;
585 }
586 if (desc->mEffects.size() == 0) {
587 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
588 delete desc;
589 return NULL;
590 }
591 return desc;
592}
593
594status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
595 const Vector <EffectDesc *>& effects)
596{
597 cnode *node = config_find(root, PREPROCESSING_TAG);
598 if (node == NULL) {
599 return -ENOENT;
600 }
601 node = node->first_child;
602 while (node) {
603 audio_source_t source = inputSourceNameToEnum(node->name);
604 if (source == AUDIO_SOURCE_CNT) {
605 ALOGW("loadInputSources() invalid input source %s", node->name);
606 node = node->next;
607 continue;
608 }
609 ALOGV("loadInputSources() loading input source %s", node->name);
610 EffectDescVector *desc = loadEffectConfig(node, effects);
611 if (desc == NULL) {
612 node = node->next;
613 continue;
614 }
615 mInputSources.add(source, desc);
616 node = node->next;
617 }
618 return NO_ERROR;
619}
620
621status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
622 const Vector <EffectDesc *>& effects)
623{
624 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
625 if (node == NULL) {
626 return -ENOENT;
627 }
628 node = node->first_child;
629 while (node) {
630 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800631 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
bryant_liuba2b4392014-06-11 16:49:30 +0800632 ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
633 node = node->next;
634 continue;
635 }
636 ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
637 EffectDescVector *desc = loadEffectConfig(node, effects);
638 if (desc == NULL) {
639 node = node->next;
640 continue;
641 }
642 mOutputStreams.add(stream, desc);
643 node = node->next;
644 }
645 return NO_ERROR;
646}
647
648AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
649{
650 cnode *node = config_find(root, UUID_TAG);
651 if (node == NULL) {
652 return NULL;
653 }
654 effect_uuid_t uuid;
655 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
656 ALOGW("loadEffect() invalid uuid %s", node->value);
657 return NULL;
658 }
659 return new EffectDesc(root->name, uuid);
660}
661
662status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
663{
664 cnode *node = config_find(root, EFFECTS_TAG);
665 if (node == NULL) {
666 return -ENOENT;
667 }
668 node = node->first_child;
669 while (node) {
670 ALOGV("loadEffects() loading effect %s", node->name);
671 EffectDesc *effect = loadEffect(node);
672 if (effect == NULL) {
673 node = node->next;
674 continue;
675 }
676 effects.add(effect);
677 node = node->next;
678 }
679 return NO_ERROR;
680}
681
682status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
683{
684 cnode *root;
685 char *data;
686
687 data = (char *)load_file(path, NULL);
688 if (data == NULL) {
689 return -ENODEV;
690 }
691 root = config_node("", "");
692 config_load(root, data);
693
694 Vector <EffectDesc *> effects;
695 loadEffects(root, effects);
696 loadInputEffectConfigurations(root, effects);
697 loadStreamEffectConfigurations(root, effects);
698
Eric Laurent182c2f52015-01-15 14:29:19 -0800699 for (size_t i = 0; i < effects.size(); i++) {
700 delete effects[i];
701 }
702
bryant_liuba2b4392014-06-11 16:49:30 +0800703 config_free(root);
704 free(root);
705 free(data);
706
707 return NO_ERROR;
708}
709
710
711}; // namespace android