blob: 654465d76f4e0b72a97db88e9dde27b0e7d32b4a [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>
Eric Laurentb6436272016-12-07 19:24:50 -080030#include <binder/IPCThreadState.h>
bryant_liuba2b4392014-06-11 16:49:30 +080031#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 Laurentfb66dd92016-01-28 18:32:03 -080060 for (i = 0; i < mInputSessions.size(); i++) {
61 mInputSessions.valueAt(i)->mEffects.clear();
62 delete mInputSessions.valueAt(i);
bryant_liuba2b4392014-06-11 16:49:30 +080063 }
Eric Laurentfb66dd92016-01-28 18:32:03 -080064 mInputSessions.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 Laurentfb66dd92016-01-28 18:32:03 -080082 audio_session_t 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 Laurentfb66dd92016-01-28 18:32:03 -080096 ssize_t idx = mInputSessions.indexOfKey(audioSession);
97 EffectVector *sessionDesc;
bryant_liuba2b4392014-06-11 16:49:30 +080098 if (idx < 0) {
Eric Laurentfb66dd92016-01-28 18:32:03 -080099 sessionDesc = new EffectVector(audioSession);
100 mInputSessions.add(audioSession, sessionDesc);
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 Laurentfb66dd92016-01-28 18:32:03 -0800103 sessionDesc = mInputSessions.valueAt(idx);
bryant_liuba2b4392014-06-11 16:49:30 +0800104 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800105 sessionDesc->mRefCount++;
bryant_liu890a5632014-08-20 18:06:13 +0800106
Eric Laurentfb66dd92016-01-28 18:32:03 -0800107 ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
108 if (sessionDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800109 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700110 Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
111 for (size_t i = 0; i < effects.size(); i++) {
112 EffectDesc *effect = effects[i];
Svet Ganovbe71aa22015-04-28 12:06:02 -0700113 sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, -1, 0,
114 0, audioSession, input);
Eric Laurent7de5ac12014-10-21 09:07:11 -0700115 status_t status = fx->initCheck();
116 if (status != NO_ERROR && status != ALREADY_EXISTS) {
117 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
118 effect->mName, (int32_t)aliasSource);
119 // fx goes out of scope and strong ref on AudioEffect is released
120 continue;
121 }
122 for (size_t j = 0; j < effect->mParams.size(); j++) {
123 fx->setParameter(effect->mParams[j]);
124 }
125 ALOGV("addInputEffects(): added Fx %s on source: %d",
bryant_liuba2b4392014-06-11 16:49:30 +0800126 effect->mName, (int32_t)aliasSource);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800127 sessionDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800128 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800129 sessionDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800130 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800131 }
bryant_liuba2b4392014-06-11 16:49:30 +0800132 return status;
133}
134
135
Eric Laurentfb66dd92016-01-28 18:32:03 -0800136status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
137 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800138{
139 status_t status = NO_ERROR;
140
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700141 Mutex::Autolock _l(mLock);
Eric Laurentfb66dd92016-01-28 18:32:03 -0800142 ssize_t index = mInputSessions.indexOfKey(audioSession);
bryant_liuba2b4392014-06-11 16:49:30 +0800143 if (index < 0) {
144 return status;
145 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800146 EffectVector *sessionDesc = mInputSessions.valueAt(index);
147 sessionDesc->mRefCount--;
148 ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
149 if (sessionDesc->mRefCount == 0) {
150 sessionDesc->setProcessorEnabled(false);
151 delete sessionDesc;
152 mInputSessions.removeItemsAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800153 ALOGV("releaseInputEffects(): all effects released");
154 }
bryant_liuba2b4392014-06-11 16:49:30 +0800155 return status;
156}
157
Eric Laurentfb66dd92016-01-28 18:32:03 -0800158status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800159 effect_descriptor_t *descriptors,
160 uint32_t *count)
161{
162 status_t status = NO_ERROR;
163
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700164 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800165 size_t index;
Eric Laurentfb66dd92016-01-28 18:32:03 -0800166 for (index = 0; index < mInputSessions.size(); index++) {
167 if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
bryant_liuba2b4392014-06-11 16:49:30 +0800168 break;
169 }
170 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800171 if (index == mInputSessions.size()) {
bryant_liuba2b4392014-06-11 16:49:30 +0800172 *count = 0;
173 return BAD_VALUE;
174 }
Eric Laurentfb66dd92016-01-28 18:32:03 -0800175 Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
bryant_liuba2b4392014-06-11 16:49:30 +0800176
177 for (size_t i = 0; i < effects.size(); i++) {
178 effect_descriptor_t desc = effects[i]->descriptor();
179 if (i < *count) {
180 descriptors[i] = desc;
181 }
182 }
183 if (effects.size() > *count) {
184 status = NO_MEMORY;
185 }
186 *count = effects.size();
187 return status;
188}
189
190
Eric Laurentfb66dd92016-01-28 18:32:03 -0800191status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
bryant_liuba2b4392014-06-11 16:49:30 +0800192 effect_descriptor_t *descriptors,
193 uint32_t *count)
194{
195 status_t status = NO_ERROR;
196
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700197 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800198 size_t index;
199 for (index = 0; index < mOutputSessions.size(); index++) {
200 if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
201 break;
202 }
203 }
204 if (index == mOutputSessions.size()) {
205 *count = 0;
206 return BAD_VALUE;
207 }
208 Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects;
209
210 for (size_t i = 0; i < effects.size(); i++) {
211 effect_descriptor_t desc = effects[i]->descriptor();
212 if (i < *count) {
213 descriptors[i] = desc;
214 }
215 }
216 if (effects.size() > *count) {
217 status = NO_MEMORY;
218 }
219 *count = effects.size();
220 return status;
221}
222
223
224status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
225 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800226 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800227{
228 status_t status = NO_ERROR;
229
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700230 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800231 // create audio processors according to stream
Eric Laurent223fd5c2014-11-11 13:43:36 -0800232 // FIXME: should we have specific post processing settings for internal streams?
233 // default to media for now.
234 if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
235 stream = AUDIO_STREAM_MUSIC;
236 }
bryant_liuba2b4392014-06-11 16:49:30 +0800237 ssize_t index = mOutputStreams.indexOfKey(stream);
238 if (index < 0) {
239 ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
240 return NO_ERROR;
241 }
242
243 ssize_t idx = mOutputSessions.indexOfKey(audioSession);
244 EffectVector *procDesc;
245 if (idx < 0) {
246 procDesc = new EffectVector(audioSession);
247 mOutputSessions.add(audioSession, procDesc);
248 } else {
bryant_liu890a5632014-08-20 18:06:13 +0800249 // EffectVector is existing and we just need to increase ref count
bryant_liuba2b4392014-06-11 16:49:30 +0800250 procDesc = mOutputSessions.valueAt(idx);
251 }
bryant_liu890a5632014-08-20 18:06:13 +0800252 procDesc->mRefCount++;
253
Eric Laurent7de5ac12014-10-21 09:07:11 -0700254 ALOGV("addOutputSessionEffects(): session: %d, refCount: %d",
255 audioSession, procDesc->mRefCount);
256 if (procDesc->mRefCount == 1) {
Eric Laurentb6436272016-12-07 19:24:50 -0800257 // make sure effects are associated to audio server even if we are executing a binder call
258 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Eric Laurent7de5ac12014-10-21 09:07:11 -0700259 Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects;
260 for (size_t i = 0; i < effects.size(); i++) {
261 EffectDesc *effect = effects[i];
Svet Ganovbe71aa22015-04-28 12:06:02 -0700262 sp<AudioEffect> fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, 0, 0, 0,
Eric Laurent7de5ac12014-10-21 09:07:11 -0700263 audioSession, output);
264 status_t status = fx->initCheck();
265 if (status != NO_ERROR && status != ALREADY_EXISTS) {
266 ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d",
267 effect->mName, audioSession);
268 // fx goes out of scope and strong ref on AudioEffect is released
269 continue;
270 }
271 ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d",
272 effect->mName, audioSession, (int32_t)stream);
273 procDesc->mEffects.add(fx);
bryant_liuba2b4392014-06-11 16:49:30 +0800274 }
Eric Laurent7de5ac12014-10-21 09:07:11 -0700275
276 procDesc->setProcessorEnabled(true);
Eric Laurentb6436272016-12-07 19:24:50 -0800277 IPCThreadState::self()->restoreCallingIdentity(token);
bryant_liuba2b4392014-06-11 16:49:30 +0800278 }
bryant_liuba2b4392014-06-11 16:49:30 +0800279 return status;
280}
281
282status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
283 audio_stream_type_t stream,
Eric Laurentfb66dd92016-01-28 18:32:03 -0800284 audio_session_t audioSession)
bryant_liuba2b4392014-06-11 16:49:30 +0800285{
286 status_t status = NO_ERROR;
287 (void) output; // argument not used for now
288 (void) stream; // argument not used for now
289
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700290 Mutex::Autolock _l(mLock);
bryant_liuba2b4392014-06-11 16:49:30 +0800291 ssize_t index = mOutputSessions.indexOfKey(audioSession);
292 if (index < 0) {
293 ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
294 return NO_ERROR;
295 }
296
297 EffectVector *procDesc = mOutputSessions.valueAt(index);
bryant_liu890a5632014-08-20 18:06:13 +0800298 procDesc->mRefCount--;
Eric Laurent7de5ac12014-10-21 09:07:11 -0700299 ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
300 audioSession, procDesc->mRefCount);
bryant_liu890a5632014-08-20 18:06:13 +0800301 if (procDesc->mRefCount == 0) {
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700302 procDesc->setProcessorEnabled(false);
bryant_liu890a5632014-08-20 18:06:13 +0800303 procDesc->mEffects.clear();
304 delete procDesc;
305 mOutputSessions.removeItemsAt(index);
306 ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
307 audioSession);
308 }
bryant_liuba2b4392014-06-11 16:49:30 +0800309 return status;
310}
311
312
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700313void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
bryant_liuba2b4392014-06-11 16:49:30 +0800314{
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700315 for (size_t i = 0; i < mEffects.size(); i++) {
316 mEffects.itemAt(i)->setEnabled(enabled);
bryant_liuba2b4392014-06-11 16:49:30 +0800317 }
318}
319
320
321// ----------------------------------------------------------------------------
322// Audio processing configuration
323// ----------------------------------------------------------------------------
324
325/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
326 MIC_SRC_TAG,
327 VOICE_UL_SRC_TAG,
328 VOICE_DL_SRC_TAG,
329 VOICE_CALL_SRC_TAG,
330 CAMCORDER_SRC_TAG,
331 VOICE_REC_SRC_TAG,
rago8a397d52015-12-02 11:27:57 -0800332 VOICE_COMM_SRC_TAG,
333 UNPROCESSED_SRC_TAG
bryant_liuba2b4392014-06-11 16:49:30 +0800334};
335
336// returns the audio_source_t enum corresponding to the input source name or
337// AUDIO_SOURCE_CNT is no match found
Eric Laurent8b1e80b2014-10-07 09:08:47 -0700338/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
bryant_liuba2b4392014-06-11 16:49:30 +0800339{
340 int i;
341 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
342 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
343 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
344 break;
345 }
346 }
347 return (audio_source_t)i;
348}
349
Eric Laurent223fd5c2014-11-11 13:43:36 -0800350const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
bryant_liuba2b4392014-06-11 16:49:30 +0800351 AUDIO_STREAM_DEFAULT_TAG,
352 AUDIO_STREAM_VOICE_CALL_TAG,
353 AUDIO_STREAM_SYSTEM_TAG,
354 AUDIO_STREAM_RING_TAG,
355 AUDIO_STREAM_MUSIC_TAG,
356 AUDIO_STREAM_ALARM_TAG,
357 AUDIO_STREAM_NOTIFICATION_TAG,
358 AUDIO_STREAM_BLUETOOTH_SCO_TAG,
359 AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
360 AUDIO_STREAM_DTMF_TAG,
361 AUDIO_STREAM_TTS_TAG
362};
363
364// returns the audio_stream_t enum corresponding to the output stream name or
Eric Laurent223fd5c2014-11-11 13:43:36 -0800365// AUDIO_STREAM_PUBLIC_CNT is no match found
bryant_liuba2b4392014-06-11 16:49:30 +0800366audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
367{
368 int i;
Eric Laurent223fd5c2014-11-11 13:43:36 -0800369 for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
bryant_liuba2b4392014-06-11 16:49:30 +0800370 if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
371 ALOGV("streamNameToEnum found stream %s %d", name, i);
372 break;
373 }
374 }
375 return (audio_stream_type_t)i;
376}
377
378// ----------------------------------------------------------------------------
379// Audio Effect Config parser
380// ----------------------------------------------------------------------------
381
Eric Laurent138ed172016-02-10 10:40:44 -0800382size_t AudioPolicyEffects::growParamSize(char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800383 size_t size,
384 size_t *curSize,
385 size_t *totSize)
386{
387 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
388 size_t pos = ((*curSize - 1 ) / size + 1) * size;
389
390 if (pos + size > *totSize) {
391 while (pos + size > *totSize) {
392 *totSize += ((*totSize + 7) / 8) * 4;
393 }
Eric Laurent138ed172016-02-10 10:40:44 -0800394 *param = (char *)realloc(*param, *totSize);
395 if (*param == NULL) {
396 ALOGE("%s realloc error for size %zu", __func__, *totSize);
397 return 0;
398 }
bryant_liuba2b4392014-06-11 16:49:30 +0800399 }
400 *curSize = pos + size;
401 return pos;
402}
403
Eric Laurent138ed172016-02-10 10:40:44 -0800404
bryant_liuba2b4392014-06-11 16:49:30 +0800405size_t AudioPolicyEffects::readParamValue(cnode *node,
Eric Laurent138ed172016-02-10 10:40:44 -0800406 char **param,
bryant_liuba2b4392014-06-11 16:49:30 +0800407 size_t *curSize,
408 size_t *totSize)
409{
Eric Laurent138ed172016-02-10 10:40:44 -0800410 size_t len = 0;
411 size_t pos;
412
bryant_liuba2b4392014-06-11 16:49:30 +0800413 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800414 pos = growParamSize(param, sizeof(short), curSize, totSize);
415 if (pos == 0) {
416 goto exit;
bryant_liuba2b4392014-06-11 16:49:30 +0800417 }
Eric Laurent138ed172016-02-10 10:40:44 -0800418 *(short *)(*param + pos) = (short)atoi(node->value);
419 ALOGV("readParamValue() reading short %d", *(short *)(*param + pos));
420 len = sizeof(short);
421 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
422 pos = growParamSize(param, sizeof(int), curSize, totSize);
423 if (pos == 0) {
424 goto exit;
425 }
426 *(int *)(*param + pos) = atoi(node->value);
427 ALOGV("readParamValue() reading int %d", *(int *)(*param + pos));
428 len = sizeof(int);
429 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
430 pos = growParamSize(param, sizeof(float), curSize, totSize);
431 if (pos == 0) {
432 goto exit;
433 }
434 *(float *)(*param + pos) = (float)atof(node->value);
435 ALOGV("readParamValue() reading float %f",*(float *)(*param + pos));
436 len = sizeof(float);
437 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
438 pos = growParamSize(param, sizeof(bool), curSize, totSize);
439 if (pos == 0) {
440 goto exit;
441 }
442 if (strncmp(node->value, "true", strlen("true") + 1) == 0) {
443 *(bool *)(*param + pos) = true;
444 } else {
445 *(bool *)(*param + pos) = false;
446 }
447 ALOGV("readParamValue() reading bool %s",
448 *(bool *)(*param + pos) ? "true" : "false");
449 len = sizeof(bool);
bryant_liuba2b4392014-06-11 16:49:30 +0800450 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
Eric Laurent138ed172016-02-10 10:40:44 -0800451 len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
bryant_liuba2b4392014-06-11 16:49:30 +0800452 if (*curSize + len + 1 > *totSize) {
453 *totSize = *curSize + len + 1;
Eric Laurent138ed172016-02-10 10:40:44 -0800454 *param = (char *)realloc(*param, *totSize);
455 if (*param == NULL) {
456 len = 0;
457 ALOGE("%s realloc error for string len %zu", __func__, *totSize);
458 goto exit;
459 }
bryant_liuba2b4392014-06-11 16:49:30 +0800460 }
Eric Laurent138ed172016-02-10 10:40:44 -0800461 strncpy(*param + *curSize, node->value, len);
bryant_liuba2b4392014-06-11 16:49:30 +0800462 *curSize += len;
Eric Laurent138ed172016-02-10 10:40:44 -0800463 (*param)[*curSize] = '\0';
464 ALOGV("readParamValue() reading string %s", *param + *curSize - len);
465 } else {
466 ALOGW("readParamValue() unknown param type %s", node->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800467 }
Eric Laurent138ed172016-02-10 10:40:44 -0800468exit:
469 return len;
bryant_liuba2b4392014-06-11 16:49:30 +0800470}
471
472effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root)
473{
474 cnode *param;
475 cnode *value;
476 size_t curSize = sizeof(effect_param_t);
477 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
478 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
479
Eric Laurent138ed172016-02-10 10:40:44 -0800480 if (fx_param == NULL) {
481 ALOGE("%s malloc error for effect structure of size %zu",
482 __func__, totSize);
483 return NULL;
484 }
485
bryant_liuba2b4392014-06-11 16:49:30 +0800486 param = config_find(root, PARAM_TAG);
487 value = config_find(root, VALUE_TAG);
488 if (param == NULL && value == NULL) {
489 // try to parse simple parameter form {int int}
490 param = root->first_child;
491 if (param != NULL) {
492 // Note: that a pair of random strings is read as 0 0
493 int *ptr = (int *)fx_param->data;
Eric Laurent138ed172016-02-10 10:40:44 -0800494#if LOG_NDEBUG == 0
bryant_liuba2b4392014-06-11 16:49:30 +0800495 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
Eric Laurent138ed172016-02-10 10:40:44 -0800496 ALOGV("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
497#endif
bryant_liuba2b4392014-06-11 16:49:30 +0800498 *ptr++ = atoi(param->name);
499 *ptr = atoi(param->value);
500 fx_param->psize = sizeof(int);
501 fx_param->vsize = sizeof(int);
502 return fx_param;
503 }
504 }
505 if (param == NULL || value == NULL) {
Eric Laurent138ed172016-02-10 10:40:44 -0800506 ALOGW("loadEffectParameter() invalid parameter description %s",
507 root->name);
bryant_liuba2b4392014-06-11 16:49:30 +0800508 goto error;
509 }
510
511 fx_param->psize = 0;
512 param = param->first_child;
513 while (param) {
514 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800515 size_t size =
516 readParamValue(param, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800517 if (size == 0) {
518 goto error;
519 }
520 fx_param->psize += size;
521 param = param->next;
522 }
523
524 // align start of value field on 32 bit boundary
525 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
526
527 fx_param->vsize = 0;
528 value = value->first_child;
529 while (value) {
530 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent138ed172016-02-10 10:40:44 -0800531 size_t size =
532 readParamValue(value, (char **)&fx_param, &curSize, &totSize);
bryant_liuba2b4392014-06-11 16:49:30 +0800533 if (size == 0) {
534 goto error;
535 }
536 fx_param->vsize += size;
537 value = value->next;
538 }
539
540 return fx_param;
541
542error:
Eric Laurent138ed172016-02-10 10:40:44 -0800543 free(fx_param);
bryant_liuba2b4392014-06-11 16:49:30 +0800544 return NULL;
545}
546
547void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
548{
549 cnode *node = root->first_child;
550 while (node) {
551 ALOGV("loadEffectParameters() loading param %s", node->name);
552 effect_param_t *param = loadEffectParameter(node);
Eric Laurent138ed172016-02-10 10:40:44 -0800553 if (param != NULL) {
554 params.add(param);
bryant_liuba2b4392014-06-11 16:49:30 +0800555 }
bryant_liuba2b4392014-06-11 16:49:30 +0800556 node = node->next;
557 }
558}
559
560
561AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig(
562 cnode *root,
563 const Vector <EffectDesc *>& effects)
564{
565 cnode *node = root->first_child;
566 if (node == NULL) {
567 ALOGW("loadInputSource() empty element %s", root->name);
568 return NULL;
569 }
570 EffectDescVector *desc = new EffectDescVector();
571 while (node) {
572 size_t i;
Eric Laurent138ed172016-02-10 10:40:44 -0800573
bryant_liuba2b4392014-06-11 16:49:30 +0800574 for (i = 0; i < effects.size(); i++) {
575 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
576 ALOGV("loadEffectConfig() found effect %s in list", node->name);
577 break;
578 }
579 }
580 if (i == effects.size()) {
581 ALOGV("loadEffectConfig() effect %s not in list", node->name);
582 node = node->next;
583 continue;
584 }
585 EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
586 loadEffectParameters(node, effect->mParams);
587 ALOGV("loadEffectConfig() adding effect %s uuid %08x",
588 effect->mName, effect->mUuid.timeLow);
589 desc->mEffects.add(effect);
590 node = node->next;
591 }
592 if (desc->mEffects.size() == 0) {
593 ALOGW("loadEffectConfig() no valid effects found in config %s", root->name);
594 delete desc;
595 return NULL;
596 }
597 return desc;
598}
599
600status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root,
601 const Vector <EffectDesc *>& effects)
602{
603 cnode *node = config_find(root, PREPROCESSING_TAG);
604 if (node == NULL) {
605 return -ENOENT;
606 }
607 node = node->first_child;
608 while (node) {
609 audio_source_t source = inputSourceNameToEnum(node->name);
610 if (source == AUDIO_SOURCE_CNT) {
611 ALOGW("loadInputSources() invalid input source %s", node->name);
612 node = node->next;
613 continue;
614 }
615 ALOGV("loadInputSources() loading input source %s", node->name);
616 EffectDescVector *desc = loadEffectConfig(node, effects);
617 if (desc == NULL) {
618 node = node->next;
619 continue;
620 }
621 mInputSources.add(source, desc);
622 node = node->next;
623 }
624 return NO_ERROR;
625}
626
627status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root,
628 const Vector <EffectDesc *>& effects)
629{
630 cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG);
631 if (node == NULL) {
632 return -ENOENT;
633 }
634 node = node->first_child;
635 while (node) {
636 audio_stream_type_t stream = streamNameToEnum(node->name);
Eric Laurent223fd5c2014-11-11 13:43:36 -0800637 if (stream == AUDIO_STREAM_PUBLIC_CNT) {
bryant_liuba2b4392014-06-11 16:49:30 +0800638 ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
639 node = node->next;
640 continue;
641 }
642 ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name);
643 EffectDescVector *desc = loadEffectConfig(node, effects);
644 if (desc == NULL) {
645 node = node->next;
646 continue;
647 }
648 mOutputStreams.add(stream, desc);
649 node = node->next;
650 }
651 return NO_ERROR;
652}
653
654AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root)
655{
656 cnode *node = config_find(root, UUID_TAG);
657 if (node == NULL) {
658 return NULL;
659 }
660 effect_uuid_t uuid;
661 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
662 ALOGW("loadEffect() invalid uuid %s", node->value);
663 return NULL;
664 }
665 return new EffectDesc(root->name, uuid);
666}
667
668status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
669{
670 cnode *node = config_find(root, EFFECTS_TAG);
671 if (node == NULL) {
672 return -ENOENT;
673 }
674 node = node->first_child;
675 while (node) {
676 ALOGV("loadEffects() loading effect %s", node->name);
677 EffectDesc *effect = loadEffect(node);
678 if (effect == NULL) {
679 node = node->next;
680 continue;
681 }
682 effects.add(effect);
683 node = node->next;
684 }
685 return NO_ERROR;
686}
687
688status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
689{
690 cnode *root;
691 char *data;
692
693 data = (char *)load_file(path, NULL);
694 if (data == NULL) {
695 return -ENODEV;
696 }
697 root = config_node("", "");
698 config_load(root, data);
699
700 Vector <EffectDesc *> effects;
701 loadEffects(root, effects);
702 loadInputEffectConfigurations(root, effects);
703 loadStreamEffectConfigurations(root, effects);
704
Eric Laurent182c2f52015-01-15 14:29:19 -0800705 for (size_t i = 0; i < effects.size(); i++) {
706 delete effects[i];
707 }
708
bryant_liuba2b4392014-06-11 16:49:30 +0800709 config_free(root);
710 free(root);
711 free(data);
712
713 return NO_ERROR;
714}
715
716
717}; // namespace android