blob: f6f82764194fb1b32804502712f920101ee9db78 [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>
26#include <hardware/audio_effect.h>
27#include <audio_effects/audio_effects_conf.h>
28#include <utils/Vector.h>
29#include <utils/SortedVector.h>
30#include <cutils/config_utils.h>
31#include "AudioPolicyEffects.h"
32#include "ServiceUtilities.h"
33
34namespace android {
35
36// ----------------------------------------------------------------------------
37// AudioPolicyEffects Implementation
38// ----------------------------------------------------------------------------
39
40AudioPolicyEffects::AudioPolicyEffects()
41{
42 // load automatic audio effect modules
43 if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
44 loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
45 } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
46 loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
47 }
48}
49
50
51AudioPolicyEffects::~AudioPolicyEffects()
52{
53 size_t i = 0;
54 // release audio input processing resources
55 for (i = 0; i < mInputSources.size(); i++) {
56 delete mInputSources.valueAt(i);
57 }
58 mInputSources.clear();
59
Eric Laurent84332aa2016-01-28 22:19:18 +000060 for (i = 0; i < mInputs.size(); i++) {
61 mInputs.valueAt(i)->mEffects.clear();
62 delete mInputs.valueAt(i);
bryant_liuba2b4392014-06-11 16:49:30 +080063 }
Eric Laurent84332aa2016-01-28 22:19:18 +000064 mInputs.clear();
bryant_liuba2b4392014-06-11 16:49:30 +080065
66 // release audio output processing resources
67 for (i = 0; i < mOutputStreams.size(); i++) {
68 delete mOutputStreams.valueAt(i);
69 }
70 mOutputStreams.clear();
71
72 for (i = 0; i < mOutputSessions.size(); i++) {
73 mOutputSessions.valueAt(i)->mEffects.clear();
74 delete mOutputSessions.valueAt(i);
75 }
76 mOutputSessions.clear();
77}
78
79
80status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
81 audio_source_t inputSource,
Eric Laurent84332aa2016-01-28 22:19:18 +000082 int audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +080083{
84 status_t status = NO_ERROR;
85
86 // create audio pre processors according to input source
87 audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
88 AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
89
Eric Laurent8b1e80b2014-10-07 09:08:47 -070090 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +080091 ssize_t index = mInputSources.indexOfKey(aliasSource);
92 if (index < 0) {
93 ALOGV("addInputEffects(): no processing needs to be attached to this source");
94 return status;
95 }
Eric Laurent84332aa2016-01-28 22:19:18 +000096 ssize_t idx = mInputs.indexOfKey(input);
97 EffectVector *inputDesc;
bryant_liuba2b4392014-06-11 16:49:30 +080098 if (idx < 0) {
Eric Laurent84332aa2016-01-28 22:19:18 +000099 inputDesc = new EffectVector(audioSession);
100 mInputs.add(input, inputDesc);
bryant_liuba2b4392014-06-11 16:49:30 +0800101 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800102 // EffectVector is existing and we just need to increase ref count
Eric Laurent84332aa2016-01-28 22:19:18 +0000103 inputDesc = mInputs.valueAt(idx);
bryant_liuba2b4392014-06-11 16:49:30 +0800104 }
Eric Laurent84332aa2016-01-28 22:19:18 +0000105 inputDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +0800106
Eric Laurent84332aa2016-01-28 22:19:18 +0000107 ALOGV("addInputEffects(): input: %d, refCount: %d", input, inputDesc->mRefCount);
108 if (inputDesc->mRefCount == 1) {
Eric Laurent7de5ac12014-10-21 09:07:11 -0700109 Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
110 for (size_t i = 0; i < effects.size(); i++) {
111 EffectDesc *effect = effects[i];
Svet Ganovbe71aa22015-04-28 12:06:02 -0700112 sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, -1, 0,
113 0, audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700114 status_t status = fx->initCheck();
115 if (status != NO_ERROR && status != ALREADY_EXISTS) {
116 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
117 effect->mName, (int32_t)aliasSource);
118 // fx goes out of scope and strong ref on AudioEffect is released
119 continue;
120 }
121 for (size_t j = 0; j < effect->mParams.size(); j++) {
122 fx->setParameter(effect->mParams[j]);
123 }
124 ALOGV("addInputEffects(): added Fx %s on source: %d",
bryant_liuba2b4392014-06-11 16:49:30 +0800125 effect->mName, (int32_t)aliasSource);
Eric Laurent84332aa2016-01-28 22:19:18 +0000126 inputDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800127 }
Eric Laurent84332aa2016-01-28 22:19:18 +0000128 inputDesc->setProcessorEnabled(true);
bryant_liuba2b4392014-06-11 16:49:30 +0800129 }
bryant_liuba2b4392014-06-11 16:49:30 +0800130 return status;
131}
132
133
Eric Laurent84332aa2016-01-28 22:19:18 +0000134status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input)
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 Laurent84332aa2016-01-28 22:19:18 +0000139 ssize_t index = mInputs.indexOfKey(input);
bryant_liuba2b4392014-06-11 16:49:30 +0800140 if (index < 0) {
141 return status;
142 }
Eric Laurent84332aa2016-01-28 22:19:18 +0000143 EffectVector *inputDesc = mInputs.valueAt(index);
144 inputDesc->mRefCount--;
145 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, inputDesc->mRefCount);
146 if (inputDesc->mRefCount == 0) {
147 inputDesc->setProcessorEnabled(false);
148 delete inputDesc;
149 mInputs.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 Laurent84332aa2016-01-28 22:19:18 +0000155status_t AudioPolicyEffects::queryDefaultInputEffects(int 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 Laurent84332aa2016-01-28 22:19:18 +0000163 for (index = 0; index < mInputs.size(); index++) {
164 if (mInputs.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800165 break;
166 }
167 }
Eric Laurent84332aa2016-01-28 22:19:18 +0000168 if (index == mInputs.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800169 *count = 0;
170 return BAD_VALUE;
171 }
Eric Laurent84332aa2016-01-28 22:19:18 +0000172 Vector< sp<AudioEffect> > effects = mInputs.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 Laurent84332aa2016-01-28 22:19:18 +0000188status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(int 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 Laurent84332aa2016-01-28 22:19:18 +0000223 int 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 Laurent84332aa2016-01-28 22:19:18 +0000278 int 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
376size_t AudioPolicyEffects::growParamSize(char *param,
377 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 }
388 param = (char *)realloc(param, *totSize);
389 }
390 *curSize = pos + size;
391 return pos;
392}
393
394size_t AudioPolicyEffects::readParamValue(cnode *node,
395 char *param,
396 size_t *curSize,
397 size_t *totSize)
398{
399 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
400 size_t pos = growParamSize(param, sizeof(short), curSize, totSize);
401 *(short *)((char *)param + pos) = (short)atoi(node->value);
402 ALOGV("readParamValue() reading short %d", *(short *)((char *)param + pos));
403 return sizeof(short);
404 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
405 size_t pos = growParamSize(param, sizeof(int), curSize, totSize);
406 *(int *)((char *)param + pos) = atoi(node->value);
407 ALOGV("readParamValue() reading int %d", *(int *)((char *)param + pos));
408 return sizeof(int);
409 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
410 size_t pos = growParamSize(param, sizeof(float), curSize, totSize);
411 *(float *)((char *)param + pos) = (float)atof(node->value);
412 ALOGV("readParamValue() reading float %f",*(float *)((char *)param + pos));
413 return sizeof(float);
414 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
415 size_t pos = growParamSize(param, sizeof(bool), curSize, totSize);
416 if (strncmp(node->value, "false", strlen("false") + 1) == 0) {
417 *(bool *)((char *)param + pos) = false;
418 } else {
419 *(bool *)((char *)param + pos) = true;
420 }
421 ALOGV("readParamValue() reading bool %s",*(bool *)((char *)param + pos) ? "true" : "false");
422 return sizeof(bool);
423 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
424 size_t len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
425 if (*curSize + len + 1 > *totSize) {
426 *totSize = *curSize + len + 1;
427 param = (char *)realloc(param, *totSize);
428 }
429 strncpy(param + *curSize, node->value, len);
430 *curSize += len;
431 param[*curSize] = '\0';
432 ALOGV("readParamValue() reading string %s", param + *curSize - len);
433 return len;
434 }
435 ALOGW("readParamValue() unknown param type %s", node->name);
436 return 0;
437}
438
439effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
440{
441 cnode *param;
442 cnode *value;
443 size_t curSize = sizeof(effect_param_t);
444 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
445 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
446
447 param = config_find(root, PARAM_TAG);
448 value = config_find(root, VALUE_TAG);
449 if (param == NULL && value == NULL) {
450 // try to parse simple parameter form {int int}
451 param = root->first_child;
452 if (param != NULL) {
453 // Note: that a pair of random strings is read as 0 0
454 int *ptr = (int *)fx_param->data;
455 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
456 ALOGW("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
457 *ptr++ = atoi(param->name);
458 *ptr = atoi(param->value);
459 fx_param->psize = sizeof(int);
460 fx_param->vsize = sizeof(int);
461 return fx_param;
462 }
463 }
464 if (param == NULL || value == NULL) {
465 ALOGW("loadEffectParameter() invalid parameter description %s", root->name);
466 goto error;
467 }
468
469 fx_param->psize = 0;
470 param = param->first_child;
471 while (param) {
472 ALOGV("loadEffectParameter() reading param of type %s", param->name);
473 size_t size = readParamValue(param, (char *)fx_param, &curSize, &totSize);
474 if (size == 0) {
475 goto error;
476 }
477 fx_param->psize += size;
478 param = param->next;
479 }
480
481 // align start of value field on 32 bit boundary
482 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
483
484 fx_param->vsize = 0;
485 value = value->first_child;
486 while (value) {
487 ALOGV("loadEffectParameter() reading value of type %s", value->name);
488 size_t size = readParamValue(value, (char *)fx_param, &curSize, &totSize);
489 if (size == 0) {
490 goto error;
491 }
492 fx_param->vsize += size;
493 value = value->next;
494 }
495
496 return fx_param;
497
498error:
499 delete fx_param;
500 return NULL;
501}
502
503void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
504{
505 cnode *node = root->first_child;
506 while (node) {
507 ALOGV("loadEffectParameters() loading param %s", node->name);
508 effect_param_t *param = loadEffectParameter(node);
509 if (param == NULL) {
510 node = node->next;
511 continue;
512 }
513 params.add(param);
514 node = node->next;
515 }
516}
517
518
519AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
520 cnode *root,
521 const Vector <EffectDesc *>& effects)
522{
523 cnode *node = root->first_child;
524 if (node == NULL) {
525 ALOGW("loadInputSource() empty element %s", root->name);
526 return NULL;
527 }
528 EffectDescVector *desc = new EffectDescVector();
529 while (node) {
530 size_t i;
531 for (i = 0; i < effects.size(); i++) {
532 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
533 ALOGV("loadEffectConfig() found effect %s in list", node->name);
534 break;
535 }
536 }
537 if (i == effects.size()) {
538 ALOGV("loadEffectConfig() effect %s not in list", node->name);
539 node = node->next;
540 continue;
541 }
542 EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
543 loadEffectParameters(node, effect->mParams);
544 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
545 effect->mName, effect->mUuid.timeLow);
546 desc->mEffects.add(effect);
547 node = node->next;
548 }
549 if (desc->mEffects.size() == 0) {
550 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
551 delete desc;
552 return NULL;
553 }
554 return desc;
555}
556
557status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
558 const Vector <EffectDesc *>& effects)
559{
560 cnode *node = config_find(root, PREPROCESSING_TAG);
561 if (node == NULL) {
562 return -ENOENT;
563 }
564 node = node->first_child;
565 while (node) {
566 audio_source_t source = inputSourceNameToEnum(node->name);
567 if (source == AUDIO_SOURCE_CNT) {
568 ALOGW("loadInputSources() invalid input source %s", node->name);
569 node = node->next;
570 continue;
571 }
572 ALOGV("loadInputSources() loading input source %s", node->name);
573 EffectDescVector *desc = loadEffectConfig(node, effects);
574 if (desc == NULL) {
575 node = node->next;
576 continue;
577 }
578 mInputSources.add(source, desc);
579 node = node->next;
580 }
581 return NO_ERROR;
582}
583
584status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
585 const Vector <EffectDesc *>& effects)
586{
587 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
588 if (node == NULL) {
589 return -ENOENT;
590 }
591 node = node->first_child;
592 while (node) {
593 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800594 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
bryant_liuba2b4392014-06-11 16:49:30 +0800595 ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
596 node = node->next;
597 continue;
598 }
599 ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
600 EffectDescVector *desc = loadEffectConfig(node, effects);
601 if (desc == NULL) {
602 node = node->next;
603 continue;
604 }
605 mOutputStreams.add(stream, desc);
606 node = node->next;
607 }
608 return NO_ERROR;
609}
610
611AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
612{
613 cnode *node = config_find(root, UUID_TAG);
614 if (node == NULL) {
615 return NULL;
616 }
617 effect_uuid_t uuid;
618 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
619 ALOGW("loadEffect() invalid uuid %s", node->value);
620 return NULL;
621 }
622 return new EffectDesc(root->name, uuid);
623}
624
625status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
626{
627 cnode *node = config_find(root, EFFECTS_TAG);
628 if (node == NULL) {
629 return -ENOENT;
630 }
631 node = node->first_child;
632 while (node) {
633 ALOGV("loadEffects() loading effect %s", node->name);
634 EffectDesc *effect = loadEffect(node);
635 if (effect == NULL) {
636 node = node->next;
637 continue;
638 }
639 effects.add(effect);
640 node = node->next;
641 }
642 return NO_ERROR;
643}
644
645status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
646{
647 cnode *root;
648 char *data;
649
650 data = (char *)load_file(path, NULL);
651 if (data == NULL) {
652 return -ENODEV;
653 }
654 root = config_node("", "");
655 config_load(root, data);
656
657 Vector <EffectDesc *> effects;
658 loadEffects(root, effects);
659 loadInputEffectConfigurations(root, effects);
660 loadStreamEffectConfigurations(root, effects);
661
Eric Laurent182c2f52015-01-15 14:29:19 -0800662 for (size_t i = 0; i < effects.size(); i++) {
663 delete effects[i];
664 }
665
bryant_liuba2b4392014-06-11 16:49:30 +0800666 config_free(root);
667 free(root);
668 free(data);
669
670 return NO_ERROR;
671}
672
673
674}; // namespace android