diff options
author | Eric Laurent <elaurent@google.com> | 2014-07-01 18:35:11 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-07-01 16:34:37 +0000 |
commit | b647abc0959b07c7568d9eeaf6b177aac3b20b60 (patch) | |
tree | 1be736b55fb0cc12b167c81018d932e002816d6b /services | |
parent | 4ebf92c0418584f1bb5ab3e83e8398351f4c05e5 (diff) | |
parent | ba2b43990a7b4f0f2c425cf6cdfc63376a45772c (diff) | |
download | frameworks_av-b647abc0959b07c7568d9eeaf6b177aac3b20b60.zip frameworks_av-b647abc0959b07c7568d9eeaf6b177aac3b20b60.tar.gz frameworks_av-b647abc0959b07c7568d9eeaf6b177aac3b20b60.tar.bz2 |
Merge "frameworks: av: services: audiopolicy: Added AudioPolicyEffects"
Diffstat (limited to 'services')
-rwxr-xr-x[-rw-r--r--] | services/audiopolicy/Android.mk | 3 | ||||
-rwxr-xr-x | services/audiopolicy/AudioPolicyEffects.cpp | 638 | ||||
-rwxr-xr-x | services/audiopolicy/AudioPolicyEffects.h | 187 | ||||
-rwxr-xr-x[-rw-r--r--] | services/audiopolicy/AudioPolicyInterfaceImpl.cpp | 87 | ||||
-rwxr-xr-x[-rw-r--r--] | services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp | 87 | ||||
-rwxr-xr-x[-rw-r--r--] | services/audiopolicy/AudioPolicyService.cpp | 329 | ||||
-rwxr-xr-x[-rw-r--r--] | services/audiopolicy/AudioPolicyService.h | 82 |
7 files changed, 883 insertions, 530 deletions
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk index cddc503..f3be42d 100644..100755 --- a/services/audiopolicy/Android.mk +++ b/services/audiopolicy/Android.mk @@ -3,7 +3,8 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - AudioPolicyService.cpp + AudioPolicyService.cpp \ + AudioPolicyEffects.cpp ifeq ($(USE_LEGACY_AUDIO_POLICY), 1) LOCAL_SRC_FILES += \ diff --git a/services/audiopolicy/AudioPolicyEffects.cpp b/services/audiopolicy/AudioPolicyEffects.cpp new file mode 100755 index 0000000..185e1cc --- /dev/null +++ b/services/audiopolicy/AudioPolicyEffects.cpp @@ -0,0 +1,638 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "AudioPolicyEffects" +#define LOG_NDEBUG 0 + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <cutils/misc.h> +#include <media/AudioEffect.h> +#include <system/audio.h> +#include <hardware/audio_effect.h> +#include <audio_effects/audio_effects_conf.h> +#include <utils/Vector.h> +#include <utils/SortedVector.h> +#include <cutils/config_utils.h> +#include "AudioPolicyEffects.h" +#include "ServiceUtilities.h" + +namespace android { + +// ---------------------------------------------------------------------------- +// AudioPolicyEffects Implementation +// ---------------------------------------------------------------------------- + +AudioPolicyEffects::AudioPolicyEffects() +{ + // load automatic audio effect modules + if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) { + loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE); + } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) { + loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE); + } +} + + +AudioPolicyEffects::~AudioPolicyEffects() +{ + size_t i = 0; + // release audio input processing resources + for (i = 0; i < mInputSources.size(); i++) { + delete mInputSources.valueAt(i); + } + mInputSources.clear(); + + for (i = 0; i < mInputs.size(); i++) { + mInputs.valueAt(i)->mEffects.clear(); + delete mInputs.valueAt(i); + } + mInputs.clear(); + + // release audio output processing resources + for (i = 0; i < mOutputStreams.size(); i++) { + delete mOutputStreams.valueAt(i); + } + mOutputStreams.clear(); + + for (i = 0; i < mOutputSessions.size(); i++) { + mOutputSessions.valueAt(i)->mEffects.clear(); + delete mOutputSessions.valueAt(i); + } + mOutputSessions.clear(); +} + + +status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input, + audio_source_t inputSource, + int audioSession) +{ + status_t status = NO_ERROR; + + // create audio pre processors according to input source + audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ? + AUDIO_SOURCE_VOICE_RECOGNITION : inputSource; + + ssize_t index = mInputSources.indexOfKey(aliasSource); + if (index < 0) { + ALOGV("addInputEffects(): no processing needs to be attached to this source"); + return status; + } + ssize_t idx = mInputs.indexOfKey(input); + EffectVector *inputDesc; + if (idx < 0) { + inputDesc = new EffectVector(audioSession); + mInputs.add(input, inputDesc); + } else { + inputDesc = mInputs.valueAt(idx); + } + + Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects; + for (size_t i = 0; i < effects.size(); i++) { + EffectDesc *effect = effects[i]; + sp<AudioEffect> fx = new AudioEffect(NULL, &effect->mUuid, -1, 0, 0, audioSession, input); + status_t status = fx->initCheck(); + if (status != NO_ERROR && status != ALREADY_EXISTS) { + ALOGW("addInputEffects(): failed to create Fx %s on source %d", + effect->mName, (int32_t)aliasSource); + // fx goes out of scope and strong ref on AudioEffect is released + continue; + } + for (size_t j = 0; j < effect->mParams.size(); j++) { + fx->setParameter(effect->mParams[j]); + } + ALOGV("addInputEffects(): added Fx %s on source: %d", effect->mName, (int32_t)aliasSource); + inputDesc->mEffects.add(fx); + } + setProcessorEnabled(inputDesc, true); + + return status; +} + + +status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input) +{ + status_t status = NO_ERROR; + + ssize_t index = mInputs.indexOfKey(input); + if (index < 0) { + return status; + } + EffectVector *inputDesc = mInputs.valueAt(index); + setProcessorEnabled(inputDesc, false); + delete inputDesc; + mInputs.removeItemsAt(index); + ALOGV("releaseInputEffects(): all effects released"); + return status; +} + +status_t AudioPolicyEffects::queryDefaultInputEffects(int audioSession, + effect_descriptor_t *descriptors, + uint32_t *count) +{ + status_t status = NO_ERROR; + + size_t index; + for (index = 0; index < mInputs.size(); index++) { + if (mInputs.valueAt(index)->mSessionId == audioSession) { + break; + } + } + if (index == mInputs.size()) { + *count = 0; + return BAD_VALUE; + } + Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects; + + for (size_t i = 0; i < effects.size(); i++) { + effect_descriptor_t desc = effects[i]->descriptor(); + if (i < *count) { + descriptors[i] = desc; + } + } + if (effects.size() > *count) { + status = NO_MEMORY; + } + *count = effects.size(); + return status; +} + + +status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(int audioSession, + effect_descriptor_t *descriptors, + uint32_t *count) +{ + status_t status = NO_ERROR; + + size_t index; + for (index = 0; index < mOutputSessions.size(); index++) { + if (mOutputSessions.valueAt(index)->mSessionId == audioSession) { + break; + } + } + if (index == mOutputSessions.size()) { + *count = 0; + return BAD_VALUE; + } + Vector< sp<AudioEffect> > effects = mOutputSessions.valueAt(index)->mEffects; + + for (size_t i = 0; i < effects.size(); i++) { + effect_descriptor_t desc = effects[i]->descriptor(); + if (i < *count) { + descriptors[i] = desc; + } + } + if (effects.size() > *count) { + status = NO_MEMORY; + } + *count = effects.size(); + return status; +} + + +status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output, + audio_stream_type_t stream, + int audioSession) +{ + status_t status = NO_ERROR; + + // create audio processors according to stream + ssize_t index = mOutputStreams.indexOfKey(stream); + if (index < 0) { + ALOGV("addOutputSessionEffects(): no output processing needed for this stream"); + return NO_ERROR; + } + + ssize_t idx = mOutputSessions.indexOfKey(audioSession); + EffectVector *procDesc; + if (idx < 0) { + procDesc = new EffectVector(audioSession); + mOutputSessions.add(audioSession, procDesc); + } else { + procDesc = mOutputSessions.valueAt(idx); + } + + Vector <EffectDesc *> effects = mOutputStreams.valueAt(index)->mEffects; + for (size_t i = 0; i < effects.size(); i++) { + EffectDesc *effect = effects[i]; + sp<AudioEffect> fx = new AudioEffect(NULL, &effect->mUuid, 0, 0, 0, audioSession, output); + status_t status = fx->initCheck(); + if (status != NO_ERROR && status != ALREADY_EXISTS) { + ALOGE("addOutputSessionEffects(): failed to create Fx %s on session %d", + effect->mName, audioSession); + // fx goes out of scope and strong ref on AudioEffect is released + continue; + } + ALOGV("addOutputSessionEffects(): added Fx %s on session: %d for stream: %d", + effect->mName, audioSession, (int32_t)stream); + procDesc->mEffects.add(fx); + } + + setProcessorEnabled(procDesc, true); + + return status; +} + +status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output, + audio_stream_type_t stream, + int audioSession) +{ + status_t status = NO_ERROR; + (void) output; // argument not used for now + (void) stream; // argument not used for now + + ssize_t index = mOutputSessions.indexOfKey(audioSession); + if (index < 0) { + ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream"); + return NO_ERROR; + } + + EffectVector *procDesc = mOutputSessions.valueAt(index); + setProcessorEnabled(procDesc, false); + procDesc->mEffects.clear(); + delete procDesc; + mOutputSessions.removeItemsAt(index); + ALOGV("releaseOutputSessionEffects(): output processing released from session: %d", + audioSession); + return status; +} + + +void AudioPolicyEffects::setProcessorEnabled(const EffectVector *effectVector, bool enabled) +{ + const Vector<sp<AudioEffect> > &fxVector = effectVector->mEffects; + for (size_t i = 0; i < fxVector.size(); i++) { + fxVector.itemAt(i)->setEnabled(enabled); + } +} + + +// ---------------------------------------------------------------------------- +// Audio processing configuration +// ---------------------------------------------------------------------------- + +/*static*/ const char * const AudioPolicyEffects::kInputSourceNames[AUDIO_SOURCE_CNT -1] = { + MIC_SRC_TAG, + VOICE_UL_SRC_TAG, + VOICE_DL_SRC_TAG, + VOICE_CALL_SRC_TAG, + CAMCORDER_SRC_TAG, + VOICE_REC_SRC_TAG, + VOICE_COMM_SRC_TAG +}; + +// returns the audio_source_t enum corresponding to the input source name or +// AUDIO_SOURCE_CNT is no match found +audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name) +{ + int i; + for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) { + if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) { + ALOGV("inputSourceNameToEnum found source %s %d", name, i); + break; + } + } + return (audio_source_t)i; +} + +const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_CNT+1] = { + AUDIO_STREAM_DEFAULT_TAG, + AUDIO_STREAM_VOICE_CALL_TAG, + AUDIO_STREAM_SYSTEM_TAG, + AUDIO_STREAM_RING_TAG, + AUDIO_STREAM_MUSIC_TAG, + AUDIO_STREAM_ALARM_TAG, + AUDIO_STREAM_NOTIFICATION_TAG, + AUDIO_STREAM_BLUETOOTH_SCO_TAG, + AUDIO_STREAM_ENFORCED_AUDIBLE_TAG, + AUDIO_STREAM_DTMF_TAG, + AUDIO_STREAM_TTS_TAG +}; + +// returns the audio_stream_t enum corresponding to the output stream name or +// AUDIO_STREAM_CNT is no match found +audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name) +{ + int i; + for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_CNT; i++) { + if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) { + ALOGV("streamNameToEnum found stream %s %d", name, i); + break; + } + } + return (audio_stream_type_t)i; +} + +// ---------------------------------------------------------------------------- +// Audio Effect Config parser +// ---------------------------------------------------------------------------- + +size_t AudioPolicyEffects::growParamSize(char *param, + size_t size, + size_t *curSize, + size_t *totSize) +{ + // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int) + size_t pos = ((*curSize - 1 ) / size + 1) * size; + + if (pos + size > *totSize) { + while (pos + size > *totSize) { + *totSize += ((*totSize + 7) / 8) * 4; + } + param = (char *)realloc(param, *totSize); + } + *curSize = pos + size; + return pos; +} + +size_t AudioPolicyEffects::readParamValue(cnode *node, + char *param, + size_t *curSize, + size_t *totSize) +{ + if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) { + size_t pos = growParamSize(param, sizeof(short), curSize, totSize); + *(short *)((char *)param + pos) = (short)atoi(node->value); + ALOGV("readParamValue() reading short %d", *(short *)((char *)param + pos)); + return sizeof(short); + } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) { + size_t pos = growParamSize(param, sizeof(int), curSize, totSize); + *(int *)((char *)param + pos) = atoi(node->value); + ALOGV("readParamValue() reading int %d", *(int *)((char *)param + pos)); + return sizeof(int); + } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) { + size_t pos = growParamSize(param, sizeof(float), curSize, totSize); + *(float *)((char *)param + pos) = (float)atof(node->value); + ALOGV("readParamValue() reading float %f",*(float *)((char *)param + pos)); + return sizeof(float); + } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) { + size_t pos = growParamSize(param, sizeof(bool), curSize, totSize); + if (strncmp(node->value, "false", strlen("false") + 1) == 0) { + *(bool *)((char *)param + pos) = false; + } else { + *(bool *)((char *)param + pos) = true; + } + ALOGV("readParamValue() reading bool %s",*(bool *)((char *)param + pos) ? "true" : "false"); + return sizeof(bool); + } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) { + size_t len = strnlen(node->value, EFFECT_STRING_LEN_MAX); + if (*curSize + len + 1 > *totSize) { + *totSize = *curSize + len + 1; + param = (char *)realloc(param, *totSize); + } + strncpy(param + *curSize, node->value, len); + *curSize += len; + param[*curSize] = '\0'; + ALOGV("readParamValue() reading string %s", param + *curSize - len); + return len; + } + ALOGW("readParamValue() unknown param type %s", node->name); + return 0; +} + +effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root) +{ + cnode *param; + cnode *value; + size_t curSize = sizeof(effect_param_t); + size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int); + effect_param_t *fx_param = (effect_param_t *)malloc(totSize); + + param = config_find(root, PARAM_TAG); + value = config_find(root, VALUE_TAG); + if (param == NULL && value == NULL) { + // try to parse simple parameter form {int int} + param = root->first_child; + if (param != NULL) { + // Note: that a pair of random strings is read as 0 0 + int *ptr = (int *)fx_param->data; + int *ptr2 = (int *)((char *)param + sizeof(effect_param_t)); + ALOGW("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2); + *ptr++ = atoi(param->name); + *ptr = atoi(param->value); + fx_param->psize = sizeof(int); + fx_param->vsize = sizeof(int); + return fx_param; + } + } + if (param == NULL || value == NULL) { + ALOGW("loadEffectParameter() invalid parameter description %s", root->name); + goto error; + } + + fx_param->psize = 0; + param = param->first_child; + while (param) { + ALOGV("loadEffectParameter() reading param of type %s", param->name); + size_t size = readParamValue(param, (char *)fx_param, &curSize, &totSize); + if (size == 0) { + goto error; + } + fx_param->psize += size; + param = param->next; + } + + // align start of value field on 32 bit boundary + curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int); + + fx_param->vsize = 0; + value = value->first_child; + while (value) { + ALOGV("loadEffectParameter() reading value of type %s", value->name); + size_t size = readParamValue(value, (char *)fx_param, &curSize, &totSize); + if (size == 0) { + goto error; + } + fx_param->vsize += size; + value = value->next; + } + + return fx_param; + +error: + delete fx_param; + return NULL; +} + +void AudioPolicyEffects::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params) +{ + cnode *node = root->first_child; + while (node) { + ALOGV("loadEffectParameters() loading param %s", node->name); + effect_param_t *param = loadEffectParameter(node); + if (param == NULL) { + node = node->next; + continue; + } + params.add(param); + node = node->next; + } +} + + +AudioPolicyEffects::EffectDescVector *AudioPolicyEffects::loadEffectConfig( + cnode *root, + const Vector <EffectDesc *>& effects) +{ + cnode *node = root->first_child; + if (node == NULL) { + ALOGW("loadInputSource() empty element %s", root->name); + return NULL; + } + EffectDescVector *desc = new EffectDescVector(); + while (node) { + size_t i; + for (i = 0; i < effects.size(); i++) { + if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) { + ALOGV("loadEffectConfig() found effect %s in list", node->name); + break; + } + } + if (i == effects.size()) { + ALOGV("loadEffectConfig() effect %s not in list", node->name); + node = node->next; + continue; + } + EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy + loadEffectParameters(node, effect->mParams); + ALOGV("loadEffectConfig() adding effect %s uuid %08x", + effect->mName, effect->mUuid.timeLow); + desc->mEffects.add(effect); + node = node->next; + } + if (desc->mEffects.size() == 0) { + ALOGW("loadEffectConfig() no valid effects found in config %s", root->name); + delete desc; + return NULL; + } + return desc; +} + +status_t AudioPolicyEffects::loadInputEffectConfigurations(cnode *root, + const Vector <EffectDesc *>& effects) +{ + cnode *node = config_find(root, PREPROCESSING_TAG); + if (node == NULL) { + return -ENOENT; + } + node = node->first_child; + while (node) { + audio_source_t source = inputSourceNameToEnum(node->name); + if (source == AUDIO_SOURCE_CNT) { + ALOGW("loadInputSources() invalid input source %s", node->name); + node = node->next; + continue; + } + ALOGV("loadInputSources() loading input source %s", node->name); + EffectDescVector *desc = loadEffectConfig(node, effects); + if (desc == NULL) { + node = node->next; + continue; + } + mInputSources.add(source, desc); + node = node->next; + } + return NO_ERROR; +} + +status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root, + const Vector <EffectDesc *>& effects) +{ + cnode *node = config_find(root, OUTPUT_SESSION_PROCESSING_TAG); + if (node == NULL) { + return -ENOENT; + } + node = node->first_child; + while (node) { + audio_stream_type_t stream = streamNameToEnum(node->name); + if (stream == AUDIO_STREAM_CNT) { + ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name); + node = node->next; + continue; + } + ALOGV("loadStreamEffectConfigurations() loading output stream %s", node->name); + EffectDescVector *desc = loadEffectConfig(node, effects); + if (desc == NULL) { + node = node->next; + continue; + } + mOutputStreams.add(stream, desc); + node = node->next; + } + return NO_ERROR; +} + +AudioPolicyEffects::EffectDesc *AudioPolicyEffects::loadEffect(cnode *root) +{ + cnode *node = config_find(root, UUID_TAG); + if (node == NULL) { + return NULL; + } + effect_uuid_t uuid; + if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) { + ALOGW("loadEffect() invalid uuid %s", node->value); + return NULL; + } + return new EffectDesc(root->name, uuid); +} + +status_t AudioPolicyEffects::loadEffects(cnode *root, Vector <EffectDesc *>& effects) +{ + cnode *node = config_find(root, EFFECTS_TAG); + if (node == NULL) { + return -ENOENT; + } + node = node->first_child; + while (node) { + ALOGV("loadEffects() loading effect %s", node->name); + EffectDesc *effect = loadEffect(node); + if (effect == NULL) { + node = node->next; + continue; + } + effects.add(effect); + node = node->next; + } + return NO_ERROR; +} + +status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path) +{ + cnode *root; + char *data; + + data = (char *)load_file(path, NULL); + if (data == NULL) { + return -ENODEV; + } + root = config_node("", ""); + config_load(root, data); + + Vector <EffectDesc *> effects; + loadEffects(root, effects); + loadInputEffectConfigurations(root, effects); + loadStreamEffectConfigurations(root, effects); + + config_free(root); + free(root); + free(data); + + return NO_ERROR; +} + + +}; // namespace android diff --git a/services/audiopolicy/AudioPolicyEffects.h b/services/audiopolicy/AudioPolicyEffects.h new file mode 100755 index 0000000..351cb1a --- /dev/null +++ b/services/audiopolicy/AudioPolicyEffects.h @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_AUDIOPOLICYEFFECTS_H +#define ANDROID_AUDIOPOLICYEFFECTS_H + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <cutils/misc.h> +#include <media/AudioEffect.h> +#include <system/audio.h> +#include <hardware/audio_effect.h> +#include <utils/Vector.h> +#include <utils/SortedVector.h> + +namespace android { + +// ---------------------------------------------------------------------------- + +// AudioPolicyEffects class +// This class will manage all effects attached to input and output streams in +// AudioPolicyService as configured in audio_effects.conf. +class AudioPolicyEffects : public RefBase +{ + +public: + + // The constructor will parse audio_effects.conf + // First it will look whether vendor specific file exists, + // otherwise it will parse the system default file. + AudioPolicyEffects(); + virtual ~AudioPolicyEffects(); + + // Return a list of effect descriptors for default input effects + // associated with audioSession + status_t queryDefaultInputEffects(int audioSession, + effect_descriptor_t *descriptors, + uint32_t *count); + + // Add all input effects associated with this input + // Effects are attached depending on the audio_source_t + status_t addInputEffects(audio_io_handle_t input, + audio_source_t inputSource, + int audioSession); + + // Add all input effects associated to this input + status_t releaseInputEffects(audio_io_handle_t input); + + + // Return a list of effect descriptors for default output effects + // associated with audioSession + status_t queryDefaultOutputSessionEffects(int audioSession, + effect_descriptor_t *descriptors, + uint32_t *count); + + // Add all output effects associated to this output + // Effects are attached depending on the audio_stream_type_t + status_t addOutputSessionEffects(audio_io_handle_t output, + audio_stream_type_t stream, + int audioSession); + + // release all output effects associated with this output stream and audiosession + status_t releaseOutputSessionEffects(audio_io_handle_t output, + audio_stream_type_t stream, + int audioSession); + +private: + + // class to store the description of an effects and its parameters + // as defined in audio_effects.conf + class EffectDesc { + public: + EffectDesc(const char *name, const effect_uuid_t& uuid) : + mName(strdup(name)), + mUuid(uuid) { } + EffectDesc(const EffectDesc& orig) : + mName(strdup(orig.mName)), + mUuid(orig.mUuid) { + // deep copy mParams + for (size_t k = 0; k < orig.mParams.size(); k++) { + effect_param_t *origParam = orig.mParams[k]; + // psize and vsize are rounded up to an int boundary for allocation + size_t origSize = sizeof(effect_param_t) + + ((origParam->psize + 3) & ~3) + + ((origParam->vsize + 3) & ~3); + effect_param_t *dupParam = (effect_param_t *) malloc(origSize); + memcpy(dupParam, origParam, origSize); + // This works because the param buffer allocation is also done by + // multiples of 4 bytes originally. In theory we should memcpy only + // the actual param size, that is without rounding vsize. + mParams.add(dupParam); + } + } + /*virtual*/ ~EffectDesc() { + free(mName); + for (size_t k = 0; k < mParams.size(); k++) { + free(mParams[k]); + } + } + char *mName; + effect_uuid_t mUuid; + Vector <effect_param_t *> mParams; + }; + + // class to store voctor of EffectDesc + class EffectDescVector { + public: + EffectDescVector() {} + /*virtual*/ ~EffectDescVector() { + for (size_t j = 0; j < mEffects.size(); j++) { + delete mEffects[j]; + } + } + Vector <EffectDesc *> mEffects; + }; + + // class to store voctor of AudioEffects + class EffectVector { + public: + EffectVector(int session) : mSessionId(session) {} + /*virtual*/ ~EffectVector() {} + const int mSessionId; + Vector< sp<AudioEffect> >mEffects; + }; + + + static const char * const kInputSourceNames[AUDIO_SOURCE_CNT -1]; + audio_source_t inputSourceNameToEnum(const char *name); + + static const char *kStreamNames[AUDIO_STREAM_CNT+1]; //+1 required as streams start from -1 + audio_stream_type_t streamNameToEnum(const char *name); + + // Enable or disable all effects in effect vector + void setProcessorEnabled(const EffectVector *effectVector, bool enabled); + + // Parse audio_effects.conf + status_t loadAudioEffectConfig(const char *path); + + // Load all effects descriptors in configuration file + status_t loadEffects(cnode *root, Vector <EffectDesc *>& effects); + EffectDesc *loadEffect(cnode *root); + + // Load all automatic effect configurations + status_t loadInputEffectConfigurations(cnode *root, const Vector <EffectDesc *>& effects); + status_t loadStreamEffectConfigurations(cnode *root, const Vector <EffectDesc *>& effects); + EffectDescVector *loadEffectConfig(cnode *root, const Vector <EffectDesc *>& effects); + + // Load all automatic effect parameters + void loadEffectParameters(cnode *root, Vector <effect_param_t *>& params); + effect_param_t *loadEffectParameter(cnode *root); + size_t readParamValue(cnode *node, + char *param, + size_t *curSize, + size_t *totSize); + size_t growParamSize(char *param, + size_t size, + size_t *curSize, + size_t *totSize); + + // Automatic input effects are configured per audio_source_t + KeyedVector< audio_source_t, EffectDescVector* > mInputSources; + // Automatic input effects are unique for audio_io_handle_t + KeyedVector< audio_io_handle_t, EffectVector* > mInputs; + + // Automatic output effects are organized per audio_stream_type_t + KeyedVector< audio_stream_type_t, EffectDescVector* > mOutputStreams; + // Automatic output effects are unique for audiosession ID + KeyedVector< int32_t, EffectVector* > mOutputSessions; +}; + +}; // namespace android + +#endif // ANDROID_AUDIOPOLICYEFFECTS_H diff --git a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp index 6342d8f..5a13ac2 100644..100755 --- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp @@ -156,6 +156,13 @@ status_t AudioPolicyService::startOutput(audio_io_handle_t output, } ALOGV("startOutput()"); Mutex::Autolock _l(mLock); + + // create audio processors according to stream + status_t status = mAudioPolicyEffects->addOutputSessionEffects(output, stream, session); + if (status != NO_ERROR && status != ALREADY_EXISTS) { + ALOGW("Failed to add effects on session %d", session); + } + return mAudioPolicyManager->startOutput(output, stream, session); } @@ -177,6 +184,13 @@ status_t AudioPolicyService::doStopOutput(audio_io_handle_t output, { ALOGV("doStopOutput from tid %d", gettid()); Mutex::Autolock _l(mLock); + + // release audio processors from the stream + status_t status = mAudioPolicyEffects->releaseOutputSessionEffects(output, stream, session); + if (status != NO_ERROR && status != ALREADY_EXISTS) { + ALOGW("Failed to release effects on session %d", session); + } + return mAudioPolicyManager->stopOutput(output, stream, session); } @@ -222,39 +236,13 @@ audio_io_handle_t AudioPolicyService::getInput(audio_source_t inputSource, if (input == 0) { return input; } - // create audio pre processors according to input source - audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ? - AUDIO_SOURCE_VOICE_RECOGNITION : inputSource; - ssize_t index = mInputSources.indexOfKey(aliasSource); - if (index < 0) { - return input; + // create audio pre processors according to input source + status_t status = mAudioPolicyEffects->addInputEffects(input, inputSource, audioSession); + if (status != NO_ERROR && status != ALREADY_EXISTS) { + ALOGW("Failed to add effects on input %d", input); } - ssize_t idx = mInputs.indexOfKey(input); - InputDesc *inputDesc; - if (idx < 0) { - inputDesc = new InputDesc(audioSession); - mInputs.add(input, inputDesc); - } else { - inputDesc = mInputs.valueAt(idx); - } - - Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects; - for (size_t i = 0; i < effects.size(); i++) { - EffectDesc *effect = effects[i]; - sp<AudioEffect> fx = new AudioEffect(NULL, &effect->mUuid, -1, 0, 0, audioSession, input); - status_t status = fx->initCheck(); - if (status != NO_ERROR && status != ALREADY_EXISTS) { - ALOGW("Failed to create Fx %s on input %d", effect->mName, input); - // fx goes out of scope and strong ref on AudioEffect is released - continue; - } - for (size_t j = 0; j < effect->mParams.size(); j++) { - fx->setParameter(effect->mParams[j]); - } - inputDesc->mEffects.add(fx); - } - setPreProcessorEnabled(inputDesc, true); + return input; } @@ -286,14 +274,11 @@ void AudioPolicyService::releaseInput(audio_io_handle_t input) Mutex::Autolock _l(mLock); mAudioPolicyManager->releaseInput(input); - ssize_t index = mInputs.indexOfKey(input); - if (index < 0) { - return; + // release audio processors from the input + status_t status = mAudioPolicyEffects->releaseInputEffects(input); + if(status != NO_ERROR) { + ALOGW("Failed to release effects on input %d", input); } - InputDesc *inputDesc = mInputs.valueAt(index); - setPreProcessorEnabled(inputDesc, false); - delete inputDesc; - mInputs.removeItemsAt(index); } status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream, @@ -436,37 +421,13 @@ status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession, effect_descriptor_t *descriptors, uint32_t *count) { - if (mAudioPolicyManager == NULL) { *count = 0; return NO_INIT; } Mutex::Autolock _l(mLock); - status_t status = NO_ERROR; - size_t index; - for (index = 0; index < mInputs.size(); index++) { - if (mInputs.valueAt(index)->mSessionId == audioSession) { - break; - } - } - if (index == mInputs.size()) { - *count = 0; - return BAD_VALUE; - } - Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects; - - for (size_t i = 0; i < effects.size(); i++) { - effect_descriptor_t desc = effects[i]->descriptor(); - if (i < *count) { - descriptors[i] = desc; - } - } - if (effects.size() > *count) { - status = NO_MEMORY; - } - *count = effects.size(); - return status; + return mAudioPolicyEffects->queryDefaultInputEffects(audioSession, descriptors, count); } bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info) diff --git a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp index 0bf4982..406988c 100644..100755 --- a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp +++ b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp @@ -144,6 +144,13 @@ status_t AudioPolicyService::startOutput(audio_io_handle_t output, } ALOGV("startOutput()"); Mutex::Autolock _l(mLock); + + // create audio processors according to stream + status_t status = mAudioPolicyEffects->addOutputSessionEffects(output, stream, session); + if (status != NO_ERROR && status != ALREADY_EXISTS) { + ALOGW("Failed to add effects on session %d", session); + } + return mpAudioPolicy->start_output(mpAudioPolicy, output, stream, session); } @@ -165,6 +172,13 @@ status_t AudioPolicyService::doStopOutput(audio_io_handle_t output, { ALOGV("doStopOutput from tid %d", gettid()); Mutex::Autolock _l(mLock); + + // release audio processors from the stream + status_t status = mAudioPolicyEffects->releaseOutputSessionEffects(output, stream, session); + if (status != NO_ERROR && status != ALREADY_EXISTS) { + ALOGW("Failed to release effects on session %d", session); + } + return mpAudioPolicy->stop_output(mpAudioPolicy, output, stream, session); } @@ -210,39 +224,13 @@ audio_io_handle_t AudioPolicyService::getInput(audio_source_t inputSource, if (input == 0) { return input; } - // create audio pre processors according to input source - audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ? - AUDIO_SOURCE_VOICE_RECOGNITION : inputSource; - ssize_t index = mInputSources.indexOfKey(aliasSource); - if (index < 0) { - return input; + // create audio pre processors according to input source + status_t status = mAudioPolicyEffects->addInputEffects(input, inputSource, audioSession); + if (status != NO_ERROR && status != ALREADY_EXISTS) { + ALOGW("Failed to add effects on input %d", input); } - ssize_t idx = mInputs.indexOfKey(input); - InputDesc *inputDesc; - if (idx < 0) { - inputDesc = new InputDesc(audioSession); - mInputs.add(input, inputDesc); - } else { - inputDesc = mInputs.valueAt(idx); - } - - Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects; - for (size_t i = 0; i < effects.size(); i++) { - EffectDesc *effect = effects[i]; - sp<AudioEffect> fx = new AudioEffect(NULL, &effect->mUuid, -1, 0, 0, audioSession, input); - status_t status = fx->initCheck(); - if (status != NO_ERROR && status != ALREADY_EXISTS) { - ALOGW("Failed to create Fx %s on input %d", effect->mName, input); - // fx goes out of scope and strong ref on AudioEffect is released - continue; - } - for (size_t j = 0; j < effect->mParams.size(); j++) { - fx->setParameter(effect->mParams[j]); - } - inputDesc->mEffects.add(fx); - } - setPreProcessorEnabled(inputDesc, true); + return input; } @@ -274,14 +262,11 @@ void AudioPolicyService::releaseInput(audio_io_handle_t input) Mutex::Autolock _l(mLock); mpAudioPolicy->release_input(mpAudioPolicy, input); - ssize_t index = mInputs.indexOfKey(input); - if (index < 0) { - return; + // release audio processors from the input + status_t status = mAudioPolicyEffects->releaseInputEffects(input); + if(status != NO_ERROR) { + ALOGW("Failed to release effects on input %d", input); } - InputDesc *inputDesc = mInputs.valueAt(index); - setPreProcessorEnabled(inputDesc, false); - delete inputDesc; - mInputs.removeItemsAt(index); } status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream, @@ -437,37 +422,13 @@ status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession, effect_descriptor_t *descriptors, uint32_t *count) { - if (mpAudioPolicy == NULL) { *count = 0; return NO_INIT; } Mutex::Autolock _l(mLock); - status_t status = NO_ERROR; - - size_t index; - for (index = 0; index < mInputs.size(); index++) { - if (mInputs.valueAt(index)->mSessionId == audioSession) { - break; - } - } - if (index == mInputs.size()) { - *count = 0; - return BAD_VALUE; - } - Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects; - for (size_t i = 0; i < effects.size(); i++) { - effect_descriptor_t desc = effects[i]->descriptor(); - if (i < *count) { - descriptors[i] = desc; - } - } - if (effects.size() > *count) { - status = NO_MEMORY; - } - *count = effects.size(); - return status; + return mAudioPolicyEffects->queryDefaultInputEffects(audioSession, descriptors, count); } bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info) diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp index 93fab11..9435797 100644..100755 --- a/services/audiopolicy/AudioPolicyService.cpp +++ b/services/audiopolicy/AudioPolicyService.cpp @@ -40,8 +40,6 @@ #include <system/audio.h> #include <system/audio_policy.h> #include <hardware/audio_policy.h> -#include <audio_effects/audio_effects_conf.h> -#include <media/AudioParameter.h> namespace android { @@ -111,12 +109,8 @@ AudioPolicyService::AudioPolicyService() mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient); #endif - // load audio pre processing modules - if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) { - loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE); - } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) { - loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE); - } + // load audio processing modules + mAudioPolicyEffects = new AudioPolicyEffects(); } AudioPolicyService::~AudioPolicyService() @@ -125,18 +119,6 @@ AudioPolicyService::~AudioPolicyService() mAudioCommandThread->exit(); mOutputCommandThread->exit(); - // release audio pre processing resources - for (size_t i = 0; i < mInputSources.size(); i++) { - delete mInputSources.valueAt(i); - } - mInputSources.clear(); - - for (size_t i = 0; i < mInputs.size(); i++) { - mInputs.valueAt(i)->mEffects.clear(); - delete mInputs.valueAt(i); - } - mInputs.clear(); - #ifdef USE_LEGACY_AUDIO_POLICY if (mpAudioPolicy != NULL && mpAudioPolicyDev != NULL) { mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy); @@ -150,6 +132,7 @@ AudioPolicyService::~AudioPolicyService() #endif mNotificationClients.clear(); + mAudioPolicyEffects.clear(); } // A notification client is always registered by AudioSystem when the client process @@ -353,14 +336,6 @@ status_t AudioPolicyService::dumpPermissionDenial(int fd) return NO_ERROR; } -void AudioPolicyService::setPreProcessorEnabled(const InputDesc *inputDesc, bool enabled) -{ - const Vector<sp<AudioEffect> > &fxVector = inputDesc->mEffects; - for (size_t i = 0; i < fxVector.size(); i++) { - fxVector.itemAt(i)->setEnabled(enabled); - } -} - status_t AudioPolicyService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { @@ -936,304 +911,6 @@ int AudioPolicyService::setVoiceVolume(float volume, int delayMs) return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs); } -// ---------------------------------------------------------------------------- -// Audio pre-processing configuration -// ---------------------------------------------------------------------------- - -/*static*/ const char * const AudioPolicyService::kInputSourceNames[AUDIO_SOURCE_CNT -1] = { - MIC_SRC_TAG, - VOICE_UL_SRC_TAG, - VOICE_DL_SRC_TAG, - VOICE_CALL_SRC_TAG, - CAMCORDER_SRC_TAG, - VOICE_REC_SRC_TAG, - VOICE_COMM_SRC_TAG -}; - -// returns the audio_source_t enum corresponding to the input source name or -// AUDIO_SOURCE_CNT is no match found -audio_source_t AudioPolicyService::inputSourceNameToEnum(const char *name) -{ - int i; - for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) { - if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) { - ALOGV("inputSourceNameToEnum found source %s %d", name, i); - break; - } - } - return (audio_source_t)i; -} - -size_t AudioPolicyService::growParamSize(char *param, - size_t size, - size_t *curSize, - size_t *totSize) -{ - // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int) - size_t pos = ((*curSize - 1 ) / size + 1) * size; - - if (pos + size > *totSize) { - while (pos + size > *totSize) { - *totSize += ((*totSize + 7) / 8) * 4; - } - param = (char *)realloc(param, *totSize); - } - *curSize = pos + size; - return pos; -} - -size_t AudioPolicyService::readParamValue(cnode *node, - char *param, - size_t *curSize, - size_t *totSize) -{ - if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) { - size_t pos = growParamSize(param, sizeof(short), curSize, totSize); - *(short *)((char *)param + pos) = (short)atoi(node->value); - ALOGV("readParamValue() reading short %d", *(short *)((char *)param + pos)); - return sizeof(short); - } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) { - size_t pos = growParamSize(param, sizeof(int), curSize, totSize); - *(int *)((char *)param + pos) = atoi(node->value); - ALOGV("readParamValue() reading int %d", *(int *)((char *)param + pos)); - return sizeof(int); - } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) { - size_t pos = growParamSize(param, sizeof(float), curSize, totSize); - *(float *)((char *)param + pos) = (float)atof(node->value); - ALOGV("readParamValue() reading float %f",*(float *)((char *)param + pos)); - return sizeof(float); - } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) { - size_t pos = growParamSize(param, sizeof(bool), curSize, totSize); - if (strncmp(node->value, "false", strlen("false") + 1) == 0) { - *(bool *)((char *)param + pos) = false; - } else { - *(bool *)((char *)param + pos) = true; - } - ALOGV("readParamValue() reading bool %s",*(bool *)((char *)param + pos) ? "true" : "false"); - return sizeof(bool); - } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) { - size_t len = strnlen(node->value, EFFECT_STRING_LEN_MAX); - if (*curSize + len + 1 > *totSize) { - *totSize = *curSize + len + 1; - param = (char *)realloc(param, *totSize); - } - strncpy(param + *curSize, node->value, len); - *curSize += len; - param[*curSize] = '\0'; - ALOGV("readParamValue() reading string %s", param + *curSize - len); - return len; - } - ALOGW("readParamValue() unknown param type %s", node->name); - return 0; -} - -effect_param_t *AudioPolicyService::loadEffectParameter(cnode *root) -{ - cnode *param; - cnode *value; - size_t curSize = sizeof(effect_param_t); - size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int); - effect_param_t *fx_param = (effect_param_t *)malloc(totSize); - - param = config_find(root, PARAM_TAG); - value = config_find(root, VALUE_TAG); - if (param == NULL && value == NULL) { - // try to parse simple parameter form {int int} - param = root->first_child; - if (param != NULL) { - // Note: that a pair of random strings is read as 0 0 - int *ptr = (int *)fx_param->data; - int *ptr2 = (int *)((char *)param + sizeof(effect_param_t)); - ALOGW("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2); - *ptr++ = atoi(param->name); - *ptr = atoi(param->value); - fx_param->psize = sizeof(int); - fx_param->vsize = sizeof(int); - return fx_param; - } - } - if (param == NULL || value == NULL) { - ALOGW("loadEffectParameter() invalid parameter description %s", root->name); - goto error; - } - - fx_param->psize = 0; - param = param->first_child; - while (param) { - ALOGV("loadEffectParameter() reading param of type %s", param->name); - size_t size = readParamValue(param, (char *)fx_param, &curSize, &totSize); - if (size == 0) { - goto error; - } - fx_param->psize += size; - param = param->next; - } - - // align start of value field on 32 bit boundary - curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int); - - fx_param->vsize = 0; - value = value->first_child; - while (value) { - ALOGV("loadEffectParameter() reading value of type %s", value->name); - size_t size = readParamValue(value, (char *)fx_param, &curSize, &totSize); - if (size == 0) { - goto error; - } - fx_param->vsize += size; - value = value->next; - } - - return fx_param; - -error: - free(fx_param); - return NULL; -} - -void AudioPolicyService::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params) -{ - cnode *node = root->first_child; - while (node) { - ALOGV("loadEffectParameters() loading param %s", node->name); - effect_param_t *param = loadEffectParameter(node); - if (param == NULL) { - node = node->next; - continue; - } - params.add(param); - node = node->next; - } -} - -AudioPolicyService::InputSourceDesc *AudioPolicyService::loadInputSource( - cnode *root, - const Vector <EffectDesc *>& effects) -{ - cnode *node = root->first_child; - if (node == NULL) { - ALOGW("loadInputSource() empty element %s", root->name); - return NULL; - } - InputSourceDesc *source = new InputSourceDesc(); - while (node) { - size_t i; - for (i = 0; i < effects.size(); i++) { - if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) { - ALOGV("loadInputSource() found effect %s in list", node->name); - break; - } - } - if (i == effects.size()) { - ALOGV("loadInputSource() effect %s not in list", node->name); - node = node->next; - continue; - } - EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy - loadEffectParameters(node, effect->mParams); - ALOGV("loadInputSource() adding effect %s uuid %08x", effect->mName, effect->mUuid.timeLow); - source->mEffects.add(effect); - node = node->next; - } - if (source->mEffects.size() == 0) { - ALOGW("loadInputSource() no valid effects found in source %s", root->name); - delete source; - return NULL; - } - return source; -} - -status_t AudioPolicyService::loadInputSources(cnode *root, const Vector <EffectDesc *>& effects) -{ - cnode *node = config_find(root, PREPROCESSING_TAG); - if (node == NULL) { - return -ENOENT; - } - node = node->first_child; - while (node) { - audio_source_t source = inputSourceNameToEnum(node->name); - if (source == AUDIO_SOURCE_CNT) { - ALOGW("loadInputSources() invalid input source %s", node->name); - node = node->next; - continue; - } - ALOGV("loadInputSources() loading input source %s", node->name); - InputSourceDesc *desc = loadInputSource(node, effects); - if (desc == NULL) { - node = node->next; - continue; - } - mInputSources.add(source, desc); - node = node->next; - } - return NO_ERROR; -} - -AudioPolicyService::EffectDesc *AudioPolicyService::loadEffect(cnode *root) -{ - cnode *node = config_find(root, UUID_TAG); - if (node == NULL) { - return NULL; - } - effect_uuid_t uuid; - if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) { - ALOGW("loadEffect() invalid uuid %s", node->value); - return NULL; - } - return new EffectDesc(root->name, uuid); -} - -status_t AudioPolicyService::loadEffects(cnode *root, Vector <EffectDesc *>& effects) -{ - cnode *node = config_find(root, EFFECTS_TAG); - if (node == NULL) { - return -ENOENT; - } - node = node->first_child; - while (node) { - ALOGV("loadEffects() loading effect %s", node->name); - EffectDesc *effect = loadEffect(node); - if (effect == NULL) { - node = node->next; - continue; - } - effects.add(effect); - node = node->next; - } - return NO_ERROR; -} - -status_t AudioPolicyService::loadPreProcessorConfig(const char *path) -{ - cnode *root; - char *data; - - data = (char *)load_file(path, NULL); - if (data == NULL) { - return -ENODEV; - } - root = config_node("", ""); - config_load(root, data); - - Vector <EffectDesc *> effects; - loadEffects(root, effects); - loadInputSources(root, effects); - - // delete effects to fix memory leak. - // as effects is local var and valgrind would treat this as memory leak - // and although it only did in mediaserver init, but free it in case mediaserver reboot - size_t i; - for (i = 0; i < effects.size(); i++) { - delete effects[i]; - } - - config_free(root); - free(root); - free(data); - - return NO_ERROR; -} - extern "C" { audio_module_handle_t aps_load_hw_module(void *service __unused, const char *name); diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h index 69673cd..380fd5e 100644..100755 --- a/services/audiopolicy/AudioPolicyService.h +++ b/services/audiopolicy/AudioPolicyService.h @@ -31,8 +31,10 @@ #include <media/ToneGenerator.h> #include <media/AudioEffect.h> #include <hardware_legacy/AudioPolicyInterface.h> +#include "AudioPolicyEffects.h" #include "AudioPolicyManager.h" + namespace android { // ---------------------------------------------------------------------------- @@ -337,60 +339,6 @@ private: wp<AudioPolicyService> mService; }; - class EffectDesc { - public: - EffectDesc(const char *name, const effect_uuid_t& uuid) : - mName(strdup(name)), - mUuid(uuid) { } - EffectDesc(const EffectDesc& orig) : - mName(strdup(orig.mName)), - mUuid(orig.mUuid) { - // deep copy mParams - for (size_t k = 0; k < orig.mParams.size(); k++) { - effect_param_t *origParam = orig.mParams[k]; - // psize and vsize are rounded up to an int boundary for allocation - size_t origSize = sizeof(effect_param_t) + - ((origParam->psize + 3) & ~3) + - ((origParam->vsize + 3) & ~3); - effect_param_t *dupParam = (effect_param_t *) malloc(origSize); - memcpy(dupParam, origParam, origSize); - // This works because the param buffer allocation is also done by - // multiples of 4 bytes originally. In theory we should memcpy only - // the actual param size, that is without rounding vsize. - mParams.add(dupParam); - } - } - /*virtual*/ ~EffectDesc() { - free(mName); - for (size_t k = 0; k < mParams.size(); k++) { - free(mParams[k]); - } - } - char *mName; - effect_uuid_t mUuid; - Vector <effect_param_t *> mParams; - }; - - class InputSourceDesc { - public: - InputSourceDesc() {} - /*virtual*/ ~InputSourceDesc() { - for (size_t j = 0; j < mEffects.size(); j++) { - delete mEffects[j]; - } - } - Vector <EffectDesc *> mEffects; - }; - - - class InputDesc { - public: - InputDesc(int session) : mSessionId(session) {} - /*virtual*/ ~InputDesc() {} - const int mSessionId; - Vector< sp<AudioEffect> >mEffects; - }; - class AudioPolicyClient : public AudioPolicyClientInterface { public: @@ -514,26 +462,6 @@ private: const sp<IAudioPolicyServiceClient> mAudioPolicyServiceClient; }; - static const char * const kInputSourceNames[AUDIO_SOURCE_CNT -1]; - - void setPreProcessorEnabled(const InputDesc *inputDesc, bool enabled); - status_t loadPreProcessorConfig(const char *path); - status_t loadEffects(cnode *root, Vector <EffectDesc *>& effects); - EffectDesc *loadEffect(cnode *root); - status_t loadInputSources(cnode *root, const Vector <EffectDesc *>& effects); - audio_source_t inputSourceNameToEnum(const char *name); - InputSourceDesc *loadInputSource(cnode *root, const Vector <EffectDesc *>& effects); - void loadEffectParameters(cnode *root, Vector <effect_param_t *>& params); - effect_param_t *loadEffectParameter(cnode *root); - size_t readParamValue(cnode *node, - char *param, - size_t *curSize, - size_t *totSize); - size_t growParamSize(char *param, - size_t size, - size_t *curSize, - size_t *totSize); - // Internal dump utilities. status_t dumpPermissionDenial(int fd); @@ -548,10 +476,10 @@ private: AudioPolicyInterface *mAudioPolicyManager; AudioPolicyClient *mAudioPolicyClient; - KeyedVector< audio_source_t, InputSourceDesc* > mInputSources; - KeyedVector< audio_io_handle_t, InputDesc* > mInputs; - DefaultKeyedVector< uid_t, sp<NotificationClient> > mNotificationClients; + + // Manage all effects configured in audio_effects.conf + sp<AudioPolicyEffects> mAudioPolicyEffects; }; }; // namespace android |