diff options
author | Eric Laurent <elaurent@google.com> | 2014-05-14 08:52:28 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2014-05-29 18:02:06 -0700 |
commit | 1afeecb88bea660b2c10b2096be0fd02433303ce (patch) | |
tree | 51538ff8734b90c48dd477bfe88734784f5ec1f7 /services | |
parent | b52c152d553556b2d227ffc943489de0c60b4b02 (diff) | |
download | frameworks_av-1afeecb88bea660b2c10b2096be0fd02433303ce.zip frameworks_av-1afeecb88bea660b2c10b2096be0fd02433303ce.tar.gz frameworks_av-1afeecb88bea660b2c10b2096be0fd02433303ce.tar.bz2 |
audio policy: parse device descriptors in config file
Implement parsing of audio_policy.conf for device and gain
controller definitions.
Copy audio_policy_conf.h from hardware_legacy.
New syntax for devices and gain controllers description will not
be parsed by legacy audio policy manager.
Bug: 14815883.
Change-Id: I7f1035d514dcf55fb3e45ed1f633a2f63ee398f5
Diffstat (limited to 'services')
-rw-r--r-- | services/audiopolicy/AudioPolicyManager.cpp | 597 | ||||
-rw-r--r-- | services/audiopolicy/AudioPolicyManager.h | 82 | ||||
-rw-r--r-- | services/audiopolicy/audio_policy_conf.h | 76 |
3 files changed, 561 insertions, 194 deletions
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp index b5b26d3..87d7771 100644 --- a/services/audiopolicy/AudioPolicyManager.cpp +++ b/services/audiopolicy/AudioPolicyManager.cpp @@ -38,9 +38,9 @@ #include <utils/Log.h> #include <hardware/audio.h> #include <hardware/audio_effect.h> -#include <hardware_legacy/audio_policy_conf.h> #include <media/AudioParameter.h> #include "AudioPolicyManager.h" +#include "audio_policy_conf.h" namespace android { @@ -136,6 +136,12 @@ const StringToEnum sInChannelsNameToEnumTable[] = { STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK), }; +const StringToEnum sGainModeNameToEnumTable[] = { + STRING_TO_ENUM(AUDIO_GAIN_MODE_JOINT), + STRING_TO_ENUM(AUDIO_GAIN_MODE_CHANNELS), + STRING_TO_ENUM(AUDIO_GAIN_MODE_RAMP), +}; + uint32_t AudioPolicyManager::stringToEnum(const struct StringToEnum *table, size_t size, @@ -188,9 +194,8 @@ status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device, if (audio_is_output_device(device)) { SortedVector <audio_io_handle_t> outputs; - sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device, - address, - 0); + sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); + devDesc->mAddress = address; ssize_t index = mAvailableOutputDevices.indexOf(devDesc); // save a copy of the opened output descriptors before any output is opened or closed @@ -295,10 +300,8 @@ status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device, if (audio_is_input_device(device)) { SortedVector <audio_io_handle_t> inputs; - sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device, - address, - 0); - + sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); + devDesc->mAddress = address; ssize_t index = mAvailableInputDevices.indexOf(devDesc); switch (state) { @@ -357,9 +360,8 @@ audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devi { audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; String8 address = String8(device_address); - sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device, - String8(device_address), - 0); + sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); + devDesc->mAddress = String8(device_address); ssize_t index; DeviceVector *deviceVector; @@ -1487,15 +1489,13 @@ status_t AudioPolicyManager::dump(int fd) snprintf(buffer, SIZE, " Available output devices:\n"); result.append(buffer); write(fd, result.string(), result.size()); - DeviceDescriptor::dumpHeader(fd, 2); for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) { - mAvailableOutputDevices[i]->dump(fd, 2); + mAvailableOutputDevices[i]->dump(fd, 2, i); } snprintf(buffer, SIZE, "\n Available input devices:\n"); write(fd, buffer, strlen(buffer)); - DeviceDescriptor::dumpHeader(fd, 2); for (size_t i = 0; i < mAvailableInputDevices.size(); i++) { - mAvailableInputDevices[i]->dump(fd, 2); + mAvailableInputDevices[i]->dump(fd, 2, i); } snprintf(buffer, SIZE, "\nHW Modules dump:\n"); @@ -1725,6 +1725,18 @@ AudioPolicyManager::HwModule *AudioPolicyManager::getModuleForDevice(audio_devic return NULL; } +AudioPolicyManager::HwModule *AudioPolicyManager::getModuleFromName(const char *name) const +{ + for (size_t i = 0; i < mHwModules.size(); i++) + { + if (strcmp(mHwModules[i]->mName, name) == 0) { + return mHwModules[i]; + } + } + return NULL; +} + + status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, audio_patch_handle_t *handle, uid_t uid) @@ -2097,7 +2109,7 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa mForceUse[i] = AUDIO_POLICY_FORCE_NONE; } - mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER); + mDefaultOutputDevice = new DeviceDescriptor(String8(""), AUDIO_DEVICE_OUT_SPEAKER); if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) { if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) { ALOGE("could not load audio policy configuration file, setting defaults"); @@ -4661,6 +4673,140 @@ AudioPolicyManager::HwModule::~HwModule() free((void *)mName); } +status_t AudioPolicyManager::HwModule::loadInput(cnode *root) +{ + cnode *node = root->first_child; + + sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SINK, this); + + while (node) { + if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) { + profile->loadSamplingRates((char *)node->value); + } else if (strcmp(node->name, FORMATS_TAG) == 0) { + profile->loadFormats((char *)node->value); + } else if (strcmp(node->name, CHANNELS_TAG) == 0) { + profile->loadInChannels((char *)node->value); + } else if (strcmp(node->name, DEVICES_TAG) == 0) { + profile->mSupportedDevices.loadDevicesFromName((char *)node->value, + mDeclaredDevices); + } else if (strcmp(node->name, GAINS_TAG) == 0) { + profile->loadGains(node); + } + node = node->next; + } + ALOGW_IF(profile->mSupportedDevices.isEmpty(), + "loadInput() invalid supported devices"); + ALOGW_IF(profile->mChannelMasks.size() == 0, + "loadInput() invalid supported channel masks"); + ALOGW_IF(profile->mSamplingRates.size() == 0, + "loadInput() invalid supported sampling rates"); + ALOGW_IF(profile->mFormats.size() == 0, + "loadInput() invalid supported formats"); + if (!profile->mSupportedDevices.isEmpty() && + (profile->mChannelMasks.size() != 0) && + (profile->mSamplingRates.size() != 0) && + (profile->mFormats.size() != 0)) { + + ALOGV("loadInput() adding input Supported Devices %04x", + profile->mSupportedDevices.types()); + + mInputProfiles.add(profile); + return NO_ERROR; + } else { + return BAD_VALUE; + } +} + +status_t AudioPolicyManager::HwModule::loadOutput(cnode *root) +{ + cnode *node = root->first_child; + + sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SOURCE, this); + + while (node) { + if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) { + profile->loadSamplingRates((char *)node->value); + } else if (strcmp(node->name, FORMATS_TAG) == 0) { + profile->loadFormats((char *)node->value); + } else if (strcmp(node->name, CHANNELS_TAG) == 0) { + profile->loadOutChannels((char *)node->value); + } else if (strcmp(node->name, DEVICES_TAG) == 0) { + profile->mSupportedDevices.loadDevicesFromName((char *)node->value, + mDeclaredDevices); + } else if (strcmp(node->name, FLAGS_TAG) == 0) { + profile->mFlags = parseFlagNames((char *)node->value); + } else if (strcmp(node->name, GAINS_TAG) == 0) { + profile->loadGains(node); + } + node = node->next; + } + ALOGW_IF(profile->mSupportedDevices.isEmpty(), + "loadOutput() invalid supported devices"); + ALOGW_IF(profile->mChannelMasks.size() == 0, + "loadOutput() invalid supported channel masks"); + ALOGW_IF(profile->mSamplingRates.size() == 0, + "loadOutput() invalid supported sampling rates"); + ALOGW_IF(profile->mFormats.size() == 0, + "loadOutput() invalid supported formats"); + if (!profile->mSupportedDevices.isEmpty() && + (profile->mChannelMasks.size() != 0) && + (profile->mSamplingRates.size() != 0) && + (profile->mFormats.size() != 0)) { + + ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x", + profile->mSupportedDevices.types(), profile->mFlags); + + mOutputProfiles.add(profile); + return NO_ERROR; + } else { + return BAD_VALUE; + } +} + +status_t AudioPolicyManager::HwModule::loadDevice(cnode *root) +{ + cnode *node = root->first_child; + + audio_devices_t type = AUDIO_DEVICE_NONE; + while (node) { + if (strcmp(node->name, DEVICE_TYPE) == 0) { + type = parseDeviceNames((char *)node->value); + break; + } + node = node->next; + } + if (type == AUDIO_DEVICE_NONE || + (!audio_is_input_device(type) && !audio_is_output_device(type))) { + ALOGW("loadDevice() bad type %08x", type); + return BAD_VALUE; + } + sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(String8(root->name), type); + deviceDesc->mModule = this; + + node = root->first_child; + while (node) { + if (strcmp(node->name, DEVICE_ADDRESS) == 0) { + deviceDesc->mAddress = String8((char *)node->value); + } else if (strcmp(node->name, CHANNELS_TAG) == 0) { + if (audio_is_input_device(type)) { + deviceDesc->loadInChannels((char *)node->value); + } else { + deviceDesc->loadOutChannels((char *)node->value); + } + } else if (strcmp(node->name, GAINS_TAG) == 0) { + deviceDesc->loadGains(node); + } + node = node->next; + } + + ALOGV("loadDevice() adding device name %s type %08x address %s", + deviceDesc->mName.string(), type, deviceDesc->mAddress.string()); + + mDeclaredDevices.add(deviceDesc); + + return NO_ERROR; +} + void AudioPolicyManager::HwModule::dump(int fd) { const size_t SIZE = 256; @@ -4688,6 +4834,12 @@ void AudioPolicyManager::HwModule::dump(int fd) mInputProfiles[i]->dump(fd); } } + if (mDeclaredDevices.size()) { + write(fd, " - devices:\n", strlen(" - devices:\n")); + for (size_t i = 0; i < mDeclaredDevices.size(); i++) { + mDeclaredDevices[i]->dump(fd, 4, i); + } + } } // --- AudioPort class implementation @@ -4732,7 +4884,6 @@ void AudioPolicyManager::AudioPort::loadSamplingRates(char *name) } str = strtok(NULL, "|"); } - return; } void AudioPolicyManager::AudioPort::loadFormats(char *name) @@ -4755,7 +4906,6 @@ void AudioPolicyManager::AudioPort::loadFormats(char *name) } str = strtok(NULL, "|"); } - return; } void AudioPolicyManager::AudioPort::loadInChannels(char *name) @@ -4780,7 +4930,6 @@ void AudioPolicyManager::AudioPort::loadInChannels(char *name) } str = strtok(NULL, "|"); } - return; } void AudioPolicyManager::AudioPort::loadOutChannels(char *name) @@ -4809,10 +4958,174 @@ void AudioPolicyManager::AudioPort::loadOutChannels(char *name) return; } +audio_gain_mode_t AudioPolicyManager::AudioPort::loadGainMode(char *name) +{ + const char *str = strtok(name, "|"); + + ALOGV("loadGainMode() %s", name); + audio_gain_mode_t mode = 0; + while (str != NULL) { + mode |= (audio_gain_mode_t)stringToEnum(sGainModeNameToEnumTable, + ARRAY_SIZE(sGainModeNameToEnumTable), + str); + str = strtok(NULL, "|"); + } + return mode; +} + +void AudioPolicyManager::AudioPort::loadGain(cnode *root) +{ + cnode *node = root->first_child; + + sp<AudioGain> gain = new AudioGain(); + + while (node) { + if (strcmp(node->name, GAIN_MODE) == 0) { + gain->mGain.mode = loadGainMode((char *)node->value); + } else if (strcmp(node->name, GAIN_CHANNELS) == 0) { + if ((mType == AUDIO_PORT_TYPE_DEVICE && mRole == AUDIO_PORT_ROLE_SOURCE) || + (mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK)) { + gain->mGain.channel_mask = + (audio_channel_mask_t)stringToEnum(sInChannelsNameToEnumTable, + ARRAY_SIZE(sInChannelsNameToEnumTable), + (char *)node->value); + } else { + gain->mGain.channel_mask = + (audio_channel_mask_t)stringToEnum(sOutChannelsNameToEnumTable, + ARRAY_SIZE(sOutChannelsNameToEnumTable), + (char *)node->value); + } + } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) { + gain->mGain.min_value = atoi((char *)node->value); + } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) { + gain->mGain.max_value = atoi((char *)node->value); + } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) { + gain->mGain.default_value = atoi((char *)node->value); + } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) { + gain->mGain.step_value = atoi((char *)node->value); + } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) { + gain->mGain.min_ramp_ms = atoi((char *)node->value); + } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) { + gain->mGain.max_ramp_ms = atoi((char *)node->value); + } + node = node->next; + } + + ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d", + gain->mGain.mode, gain->mGain.channel_mask, gain->mGain.min_value, gain->mGain.max_value); + + if (gain->mGain.mode == 0) { + return; + } + mGains.add(gain); +} + +void AudioPolicyManager::AudioPort::loadGains(cnode *root) +{ + cnode *node = root->first_child; + while (node) { + ALOGV("loadGains() loading gain %s", node->name); + loadGain(node); + node = node->next; + } +} + +void AudioPolicyManager::AudioPort::dump(int fd, int spaces) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + if (mName.size() != 0) { + snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string()); + result.append(buffer); + } + + if (mSamplingRates.size() != 0) { + snprintf(buffer, SIZE, "%*s- sampling rates: ", spaces, ""); + result.append(buffer); + for (size_t i = 0; i < mSamplingRates.size(); i++) { + snprintf(buffer, SIZE, "%d", mSamplingRates[i]); + result.append(buffer); + result.append(i == (mSamplingRates.size() - 1) ? "" : ", "); + } + result.append("\n"); + } + + if (mChannelMasks.size() != 0) { + snprintf(buffer, SIZE, "%*s- channel masks: ", spaces, ""); + result.append(buffer); + for (size_t i = 0; i < mChannelMasks.size(); i++) { + snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]); + result.append(buffer); + result.append(i == (mChannelMasks.size() - 1) ? "" : ", "); + } + result.append("\n"); + } + + if (mFormats.size() != 0) { + snprintf(buffer, SIZE, "%*s- formats: ", spaces, ""); + result.append(buffer); + for (size_t i = 0; i < mFormats.size(); i++) { + snprintf(buffer, SIZE, "%-48s", enumToString(sFormatNameToEnumTable, + ARRAY_SIZE(sFormatNameToEnumTable), + mFormats[i])); + result.append(buffer); + result.append(i == (mFormats.size() - 1) ? "" : ", "); + } + result.append("\n"); + } + write(fd, result.string(), result.size()); + if (mGains.size() != 0) { + snprintf(buffer, SIZE, "%*s- gains:\n", spaces, ""); + write(fd, buffer, strlen(buffer) + 1); + result.append(buffer); + for (size_t i = 0; i < mGains.size(); i++) { + mGains[i]->dump(fd, spaces + 2, i); + } + } +} + +// --- AudioGain class implementation + +AudioPolicyManager::AudioGain::AudioGain() +{ + memset(&mGain, 0, sizeof(struct audio_gain)); +} + +void AudioPolicyManager::AudioGain::dump(int fd, int spaces, int index) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + snprintf(buffer, SIZE, "%*sGain %d:\n", spaces, "", index+1); + result.append(buffer); + snprintf(buffer, SIZE, "%*s- mode: %08x\n", spaces, "", mGain.mode); + result.append(buffer); + snprintf(buffer, SIZE, "%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask); + result.append(buffer); + snprintf(buffer, SIZE, "%*s- min_value: %d mB\n", spaces, "", mGain.min_value); + result.append(buffer); + snprintf(buffer, SIZE, "%*s- max_value: %d mB\n", spaces, "", mGain.max_value); + result.append(buffer); + snprintf(buffer, SIZE, "%*s- default_value: %d mB\n", spaces, "", mGain.default_value); + result.append(buffer); + snprintf(buffer, SIZE, "%*s- step_value: %d mB\n", spaces, "", mGain.step_value); + result.append(buffer); + snprintf(buffer, SIZE, "%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms); + result.append(buffer); + snprintf(buffer, SIZE, "%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms); + result.append(buffer); + + write(fd, result.string(), result.size()); +} + // --- IOProfile class implementation -AudioPolicyManager::IOProfile::IOProfile(audio_port_role_t role, HwModule *module) - : AudioPort(AUDIO_PORT_TYPE_MIX, role, module), mFlags((audio_output_flags_t)0) +AudioPolicyManager::IOProfile::IOProfile(const String8& name, audio_port_role_t role, + HwModule *module) + : AudioPort(name, AUDIO_PORT_TYPE_MIX, role, module), mFlags((audio_output_flags_t)0) { } @@ -4876,42 +5189,16 @@ void AudioPolicyManager::IOProfile::dump(int fd) char buffer[SIZE]; String8 result; - snprintf(buffer, SIZE, " - sampling rates: "); - result.append(buffer); - for (size_t i = 0; i < mSamplingRates.size(); i++) { - snprintf(buffer, SIZE, "%d", mSamplingRates[i]); - result.append(buffer); - result.append(i == (mSamplingRates.size() - 1) ? "\n" : ", "); - } + AudioPort::dump(fd, 4); - snprintf(buffer, SIZE, " - channel masks: "); - result.append(buffer); - for (size_t i = 0; i < mChannelMasks.size(); i++) { - snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]); - result.append(buffer); - result.append(i == (mChannelMasks.size() - 1) ? "\n" : ", "); - } - - snprintf(buffer, SIZE, " - formats: "); + snprintf(buffer, SIZE, " - flags: 0x%04x\n", mFlags); result.append(buffer); - for (size_t i = 0; i < mFormats.size(); i++) { - snprintf(buffer, SIZE, "0x%08x", mFormats[i]); - result.append(buffer); - result.append(i == (mFormats.size() - 1) ? "\n" : ", "); - } - snprintf(buffer, SIZE, " - devices:\n"); result.append(buffer); write(fd, result.string(), result.size()); - DeviceDescriptor::dumpHeader(fd, 6); for (size_t i = 0; i < mSupportedDevices.size(); i++) { - mSupportedDevices[i]->dump(fd, 6); + mSupportedDevices[i]->dump(fd, 6, i); } - - snprintf(buffer, SIZE, " - flags: 0x%04x\n", mFlags); - result.append(buffer); - - write(fd, result.string(), result.size()); } void AudioPolicyManager::IOProfile::log() @@ -5016,10 +5303,33 @@ void AudioPolicyManager::DeviceVector::loadDevicesFromType(audio_devices_t types uint32_t i = 31 - __builtin_clz(types); uint32_t type = 1 << i; types &= ~type; - add(new DeviceDescriptor(type | role_bit)); + add(new DeviceDescriptor(String8(""), type | role_bit)); } } +void AudioPolicyManager::DeviceVector::loadDevicesFromName(char *name, + const DeviceVector& declaredDevices) +{ + char *devName = strtok(name, "|"); + while (devName != NULL) { + if (strlen(devName) != 0) { + audio_devices_t type = stringToEnum(sDeviceNameToEnumTable, + ARRAY_SIZE(sDeviceNameToEnumTable), + devName); + if (type != AUDIO_DEVICE_NONE) { + add(new DeviceDescriptor(String8(""), type)); + } else { + sp<DeviceDescriptor> deviceDesc = + declaredDevices.getDeviceFromName(String8(devName)); + if (deviceDesc != 0) { + add(deviceDesc); + } + } + } + devName = strtok(NULL, "|"); + } +} + sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDevice( audio_devices_t type, String8 address) const { @@ -5066,6 +5376,19 @@ AudioPolicyManager::DeviceVector AudioPolicyManager::DeviceVector::getDevicesFro return devices; } +sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDeviceFromName( + const String8& name) const +{ + sp<DeviceDescriptor> device; + for (size_t i = 0; i < size(); i++) { + if (itemAt(i)->mName == name) { + device = itemAt(i); + break; + } + } + return device; +} + void AudioPolicyManager::DeviceDescriptor::toAudioPortConfig( struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig) const @@ -5102,28 +5425,33 @@ void AudioPolicyManager::DeviceDescriptor::toAudioPort(struct audio_port *port) strncpy(port->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN); } -void AudioPolicyManager::DeviceDescriptor::dumpHeader(int fd, int spaces) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - - snprintf(buffer, SIZE, "%*s%-48s %-2s %-8s %-32s \n", - spaces, "", "Type", "ID", "Cnl Mask", "Address"); - write(fd, buffer, strlen(buffer)); -} - -status_t AudioPolicyManager::DeviceDescriptor::dump(int fd, int spaces) const +status_t AudioPolicyManager::DeviceDescriptor::dump(int fd, int spaces, int index) const { const size_t SIZE = 256; char buffer[SIZE]; + String8 result; - snprintf(buffer, SIZE, "%*s%-48s %2d %08x %-32s \n", - spaces, "", - enumToString(sDeviceNameToEnumTable, - ARRAY_SIZE(sDeviceNameToEnumTable), - mDeviceType), - mId, mChannelMask, mAddress.string()); - write(fd, buffer, strlen(buffer)); + snprintf(buffer, SIZE, "%*sDevice %d:\n", spaces, "", index+1); + result.append(buffer); + if (mId != 0) { + snprintf(buffer, SIZE, "%*s- id: %2d\n", spaces, "", mId); + result.append(buffer); + } + snprintf(buffer, SIZE, "%*s- type: %-48s\n", spaces, "", + enumToString(sDeviceNameToEnumTable, + ARRAY_SIZE(sDeviceNameToEnumTable), + mDeviceType)); + result.append(buffer); + if (mAddress.size() != 0) { + snprintf(buffer, SIZE, "%*s- address: %-32s\n", spaces, "", mAddress.string()); + result.append(buffer); + } + if (mChannelMask != AUDIO_CHANNEL_NONE) { + snprintf(buffer, SIZE, "%*s- channel mask: %08x\n", spaces, "", mChannelMask); + result.append(buffer); + } + write(fd, result.string(), result.size()); + AudioPort::dump(fd, spaces); return NO_ERROR; } @@ -5172,102 +5500,30 @@ audio_devices_t AudioPolicyManager::parseDeviceNames(char *name) return device; } -status_t AudioPolicyManager::loadInput(cnode *root, HwModule *module) -{ - cnode *node = root->first_child; - - sp<IOProfile> profile = new IOProfile(AUDIO_PORT_ROLE_SINK, module); - - while (node) { - if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) { - profile->loadSamplingRates((char *)node->value); - } else if (strcmp(node->name, FORMATS_TAG) == 0) { - profile->loadFormats((char *)node->value); - } else if (strcmp(node->name, CHANNELS_TAG) == 0) { - profile->loadInChannels((char *)node->value); - } else if (strcmp(node->name, DEVICES_TAG) == 0) { - profile->mSupportedDevices.loadDevicesFromType(parseDeviceNames((char *)node->value)); - } - node = node->next; - } - ALOGW_IF(profile->mSupportedDevices.isEmpty(), - "loadInput() invalid supported devices"); - ALOGW_IF(profile->mChannelMasks.size() == 0, - "loadInput() invalid supported channel masks"); - ALOGW_IF(profile->mSamplingRates.size() == 0, - "loadInput() invalid supported sampling rates"); - ALOGW_IF(profile->mFormats.size() == 0, - "loadInput() invalid supported formats"); - if (!profile->mSupportedDevices.isEmpty() && - (profile->mChannelMasks.size() != 0) && - (profile->mSamplingRates.size() != 0) && - (profile->mFormats.size() != 0)) { - - ALOGV("loadInput() adding input Supported Devices %04x", - profile->mSupportedDevices.types()); - - module->mInputProfiles.add(profile); - return NO_ERROR; - } else { - return BAD_VALUE; - } -} - -status_t AudioPolicyManager::loadOutput(cnode *root, HwModule *module) -{ - cnode *node = root->first_child; - - sp<IOProfile> profile = new IOProfile(AUDIO_PORT_ROLE_SOURCE, module); - - while (node) { - if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) { - profile->loadSamplingRates((char *)node->value); - } else if (strcmp(node->name, FORMATS_TAG) == 0) { - profile->loadFormats((char *)node->value); - } else if (strcmp(node->name, CHANNELS_TAG) == 0) { - profile->loadOutChannels((char *)node->value); - } else if (strcmp(node->name, DEVICES_TAG) == 0) { - profile->mSupportedDevices.loadDevicesFromType(parseDeviceNames((char *)node->value)); - } else if (strcmp(node->name, FLAGS_TAG) == 0) { - profile->mFlags = parseFlagNames((char *)node->value); - } - node = node->next; - } - ALOGW_IF(profile->mSupportedDevices.isEmpty(), - "loadOutput() invalid supported devices"); - ALOGW_IF(profile->mChannelMasks.size() == 0, - "loadOutput() invalid supported channel masks"); - ALOGW_IF(profile->mSamplingRates.size() == 0, - "loadOutput() invalid supported sampling rates"); - ALOGW_IF(profile->mFormats.size() == 0, - "loadOutput() invalid supported formats"); - if (!profile->mSupportedDevices.isEmpty() && - (profile->mChannelMasks.size() != 0) && - (profile->mSamplingRates.size() != 0) && - (profile->mFormats.size() != 0)) { - - ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x", - profile->mSupportedDevices.types(), profile->mFlags); - - module->mOutputProfiles.add(profile); - return NO_ERROR; - } else { - return BAD_VALUE; - } -} - void AudioPolicyManager::loadHwModule(cnode *root) { - cnode *node = config_find(root, OUTPUTS_TAG); status_t status = NAME_NOT_FOUND; - + cnode *node; HwModule *module = new HwModule(root->name); + node = config_find(root, DEVICES_TAG); + if (node != NULL) { + node = node->first_child; + while (node) { + ALOGV("loadHwModule() loading device %s", node->name); + status_t tmpStatus = module->loadDevice(node); + if (status == NAME_NOT_FOUND || status == NO_ERROR) { + status = tmpStatus; + } + node = node->next; + } + } + node = config_find(root, OUTPUTS_TAG); if (node != NULL) { node = node->first_child; while (node) { ALOGV("loadHwModule() loading output %s", node->name); - status_t tmpStatus = loadOutput(node, module); + status_t tmpStatus = module->loadOutput(node); if (status == NAME_NOT_FOUND || status == NO_ERROR) { status = tmpStatus; } @@ -5279,13 +5535,15 @@ void AudioPolicyManager::loadHwModule(cnode *root) node = node->first_child; while (node) { ALOGV("loadHwModule() loading input %s", node->name); - status_t tmpStatus = loadInput(node, module); + status_t tmpStatus = module->loadInput(node); if (status == NAME_NOT_FOUND || status == NO_ERROR) { status = tmpStatus; } node = node->next; } } + loadGlobalConfig(root, module); + if (status == NO_ERROR) { mHwModules.add(module); } else { @@ -5308,16 +5566,22 @@ void AudioPolicyManager::loadHwModules(cnode *root) } } -void AudioPolicyManager::loadGlobalConfig(cnode *root) +void AudioPolicyManager::loadGlobalConfig(cnode *root, HwModule *module) { cnode *node = config_find(root, GLOBAL_CONFIG_TAG); if (node == NULL) { return; } + DeviceVector declaredDevices; + if (module != NULL) { + declaredDevices = module->mDeclaredDevices; + } + node = node->first_child; while (node) { if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) { - mAvailableOutputDevices.loadDevicesFromType(parseDeviceNames((char *)node->value)); + mAvailableOutputDevices.loadDevicesFromName((char *)node->value, + declaredDevices); ALOGV("loadGlobalConfig() Attached Output Devices %08x", mAvailableOutputDevices.types()); } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) { @@ -5325,13 +5589,14 @@ void AudioPolicyManager::loadGlobalConfig(cnode *root) ARRAY_SIZE(sDeviceNameToEnumTable), (char *)node->value); if (device != AUDIO_DEVICE_NONE) { - mDefaultOutputDevice = new DeviceDescriptor(device); + mDefaultOutputDevice = new DeviceDescriptor(String8(""), device); } else { ALOGW("loadGlobalConfig() default device not specified"); } ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", mDefaultOutputDevice->mDeviceType); } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) { - mAvailableInputDevices.loadDevicesFromType(parseDeviceNames((char *)node->value)); + mAvailableInputDevices.loadDevicesFromName((char *)node->value, + declaredDevices); ALOGV("loadGlobalConfig() Available InputDevices %08x", mAvailableInputDevices.types()); } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) { mSpeakerDrcEnabled = stringToBool((char *)node->value); @@ -5353,9 +5618,9 @@ status_t AudioPolicyManager::loadAudioPolicyConfig(const char *path) root = config_node("", ""); config_load(root, data); - loadGlobalConfig(root); loadHwModules(root); - + // legacy audio_policy.conf files have one global_configuration section + loadGlobalConfig(root, getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)); config_free(root); free(root); free(data); @@ -5369,13 +5634,13 @@ void AudioPolicyManager::defaultAudioPolicyConfig(void) { HwModule *module; sp<IOProfile> profile; - sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC); + sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(String8(""), AUDIO_DEVICE_IN_BUILTIN_MIC); mAvailableOutputDevices.add(mDefaultOutputDevice); mAvailableInputDevices.add(defaultInputDevice); module = new HwModule("primary"); - profile = new IOProfile(AUDIO_PORT_ROLE_SOURCE, module); + profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SOURCE, module); profile->mSamplingRates.add(44100); profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT); profile->mChannelMasks.add(AUDIO_CHANNEL_OUT_STEREO); @@ -5383,7 +5648,7 @@ void AudioPolicyManager::defaultAudioPolicyConfig(void) profile->mFlags = AUDIO_OUTPUT_FLAG_PRIMARY; module->mOutputProfiles.add(profile); - profile = new IOProfile(AUDIO_PORT_ROLE_SINK, module); + profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SINK, module); profile->mSamplingRates.add(8000); profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT); profile->mChannelMasks.add(AUDIO_CHANNEL_IN_MONO); diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h index 99d9feb..e012d63 100644 --- a/services/audiopolicy/AudioPolicyManager.h +++ b/services/audiopolicy/AudioPolicyManager.h @@ -190,26 +190,25 @@ protected: DEVICE_CATEGORY_CNT }; - class IOProfile; + class HwModule; - class HwModule { + class AudioGain: public RefBase + { public: - HwModule(const char *name); - ~HwModule(); + AudioGain(); + virtual ~AudioGain() {} - void dump(int fd); + void dump(int fd, int spaces, int index) const; - const char *const mName; // base name of the audio HW module (primary, a2dp ...) - audio_module_handle_t mHandle; - Vector < sp<IOProfile> > mOutputProfiles; // output profiles exposed by this module - Vector < sp<IOProfile> > mInputProfiles; // input profiles exposed by this module + struct audio_gain mGain; }; class AudioPort: public RefBase { public: - AudioPort(audio_port_type_t type, audio_port_role_t role, HwModule *module) : - mType(type), mRole(role), mModule(module) {} + AudioPort(const String8& name, audio_port_type_t type, + audio_port_role_t role, HwModule *module) : + mName(name), mType(type), mRole(role), mModule(module) {} virtual ~AudioPort() {} virtual void toAudioPort(struct audio_port *port) const; @@ -219,15 +218,23 @@ protected: void loadOutChannels(char *name); void loadInChannels(char *name); - audio_port_type_t mType; - audio_port_role_t mRole; + audio_gain_mode_t loadGainMode(char *name); + void loadGain(cnode *root); + void loadGains(cnode *root); + + void dump(int fd, int spaces) const; + + String8 mName; + audio_port_type_t mType; + audio_port_role_t mRole; // by convention, "0' in the first entry in mSamplingRates, mChannelMasks or mFormats // indicates the supported parameters should be read from the output stream // after it is opened for the first time Vector <uint32_t> mSamplingRates; // supported sampling rates Vector <audio_channel_mask_t> mChannelMasks; // supported channel masks Vector <audio_format_t> mFormats; // supported audio formats - HwModule *mModule; // audio HW module exposing this I/O stream + Vector < sp<AudioGain> > mGains; // gain controllers + HwModule *mModule; // audio HW module exposing this I/O stream }; class AudioPatch: public RefBase @@ -246,17 +253,17 @@ protected: class DeviceDescriptor: public AudioPort { public: - DeviceDescriptor(audio_devices_t type, String8 address, + DeviceDescriptor(const String8& name, audio_devices_t type, String8 address, audio_channel_mask_t channelMask) : - AudioPort(AUDIO_PORT_TYPE_DEVICE, + AudioPort(name, AUDIO_PORT_TYPE_DEVICE, audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE, NULL), mDeviceType(type), mAddress(address), mChannelMask(channelMask), mId(0) {} - DeviceDescriptor(audio_devices_t type) : - AudioPort(AUDIO_PORT_TYPE_DEVICE, + DeviceDescriptor(String8 name, audio_devices_t type) : + AudioPort(name, AUDIO_PORT_TYPE_DEVICE, audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE, NULL), @@ -267,10 +274,10 @@ protected: bool equals(const sp<DeviceDescriptor>& other) const; void toAudioPortConfig(struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig = NULL) const; + virtual void toAudioPort(struct audio_port *port) const; - status_t dump(int fd, int spaces) const; - static void dumpHeader(int fd, int spaces); + status_t dump(int fd, int spaces, int index) const; audio_devices_t mDeviceType; String8 mAddress; @@ -290,9 +297,12 @@ protected: audio_devices_t types() const { return mDeviceTypes; } void loadDevicesFromType(audio_devices_t types); + void loadDevicesFromName(char *name, const DeviceVector& declaredDevices); + sp<DeviceDescriptor> getDevice(audio_devices_t type, String8 address) const; DeviceVector getDevicesFromType(audio_devices_t types) const; sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const; + sp<DeviceDescriptor> getDeviceFromName(const String8& name) const; private: void refreshTypes(); @@ -307,7 +317,7 @@ protected: class IOProfile : public AudioPort { public: - IOProfile(audio_port_role_t role, HwModule *module); + IOProfile(const String8& name, audio_port_role_t role, HwModule *module); virtual ~IOProfile(); bool isCompatibleProfile(audio_devices_t device, @@ -325,6 +335,25 @@ protected: // direct output...). For outputs only. }; + class HwModule { + public: + HwModule(const char *name); + ~HwModule(); + + status_t loadOutput(cnode *root); + status_t loadInput(cnode *root); + status_t loadDevice(cnode *root); + + void dump(int fd); + + const char *const mName; // base name of the audio HW module (primary, a2dp ...) + audio_module_handle_t mHandle; + Vector < sp<IOProfile> > mOutputProfiles; // output profiles exposed by this module + Vector < sp<IOProfile> > mInputProfiles; // input profiles exposed by this module + DeviceVector mDeclaredDevices; // devices declared in audio_policy.conf + + }; + // default volume curve static const VolumeCurvePoint sDefaultVolumeCurve[AudioPolicyManager::VOLCNT]; // default volume curve for media strategy @@ -633,6 +662,7 @@ protected: AudioOutputDescriptor *getOutputFromId(audio_port_handle_t id) const; AudioInputDescriptor *getInputFromId(audio_port_handle_t id) const; HwModule *getModuleForDevice(audio_devices_t device) const; + HwModule *getModuleFromName(const char *name) const; // // Audio policy configuration file parsing (audio_policy.conf) // @@ -645,11 +675,9 @@ protected: static bool stringToBool(const char *value); static audio_output_flags_t parseFlagNames(char *name); static audio_devices_t parseDeviceNames(char *name); - status_t loadOutput(cnode *root, HwModule *module); - status_t loadInput(cnode *root, HwModule *module); void loadHwModule(cnode *root); void loadHwModules(cnode *root); - void loadGlobalConfig(cnode *root); + void loadGlobalConfig(cnode *root, HwModule *module); status_t loadAudioPolicyConfig(const char *path); void defaultAudioPolicyConfig(void); @@ -663,10 +691,8 @@ protected: // reset to mOutputs when updateDevicesAndOutputs() is called. DefaultKeyedVector<audio_io_handle_t, AudioOutputDescriptor *> mPreviousOutputs; DefaultKeyedVector<audio_io_handle_t, AudioInputDescriptor *> mInputs; // list of input descriptors - DeviceVector mAvailableOutputDevices; // bit field of all available output devices - DeviceVector mAvailableInputDevices; // bit field of all available input devices - // without AUDIO_DEVICE_BIT_IN to allow direct bit - // field comparisons + DeviceVector mAvailableOutputDevices; // all available output devices + DeviceVector mAvailableInputDevices; // all available input devices int mPhoneState; // current phone state audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT]; // current forced use configuration diff --git a/services/audiopolicy/audio_policy_conf.h b/services/audiopolicy/audio_policy_conf.h new file mode 100644 index 0000000..79f20f1 --- /dev/null +++ b/services/audiopolicy/audio_policy_conf.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2012 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_AUDIO_POLICY_CONF_H +#define ANDROID_AUDIO_POLICY_CONF_H + + +///////////////////////////////////////////////// +// Definitions for audio policy configuration file (audio_policy.conf) +///////////////////////////////////////////////// + +#define AUDIO_HARDWARE_MODULE_ID_MAX_LEN 32 + +#define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf" +#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf" + +// global configuration +#define GLOBAL_CONFIG_TAG "global_configuration" + +#define ATTACHED_OUTPUT_DEVICES_TAG "attached_output_devices" +#define DEFAULT_OUTPUT_DEVICE_TAG "default_output_device" +#define ATTACHED_INPUT_DEVICES_TAG "attached_input_devices" +#define SPEAKER_DRC_ENABLED_TAG "speaker_drc_enabled" + +// hw modules descriptions +#define AUDIO_HW_MODULE_TAG "audio_hw_modules" + +#define OUTPUTS_TAG "outputs" +#define INPUTS_TAG "inputs" + +#define SAMPLING_RATES_TAG "sampling_rates" +#define FORMATS_TAG "formats" +#define CHANNELS_TAG "channel_masks" +#define DEVICES_TAG "devices" +#define FLAGS_TAG "flags" + +#define DYNAMIC_VALUE_TAG "dynamic" // special value for "channel_masks", "sampling_rates" and + // "formats" in outputs descriptors indicating that supported + // values should be queried after opening the output. + +#define DEVICES_TAG "devices" +#define DEVICE_TYPE "type" +#define DEVICE_ADDRESS "address" + +#define MIXERS_TAG "mixers" +#define MIXER_TYPE "type" +#define MIXER_TYPE_MUX "mux" +#define MIXER_TYPE_MIX "mix" + +#define GAINS_TAG "gains" +#define GAIN_MODE "mode" +#define GAIN_CHANNELS "channel_mask" +#define GAIN_MIN_VALUE "min_value_mB" +#define GAIN_MAX_VALUE "max_value_mB" +#define GAIN_DEFAULT_VALUE "default_value_mB" +#define GAIN_STEP_VALUE "step_value_mB" +#define GAIN_MIN_RAMP_MS "min_ramp_ms" +#define GAIN_MAX_RAMP_MS "max_ramp_ms" + + + +#endif // ANDROID_AUDIO_POLICY_CONF_H |