diff options
author | Eric Laurent <elaurent@google.com> | 2014-06-03 13:32:54 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2014-06-04 09:30:28 -0700 |
commit | a121f90f388343dc48793cbc7eb899aba42e7664 (patch) | |
tree | a35526f7ec819e7e539c537fcf4b1b3b5d06a6fc | |
parent | 1f2f2230900581e5de9cf01a883e5d9338f0df94 (diff) | |
download | frameworks_av-a121f90f388343dc48793cbc7eb899aba42e7664.zip frameworks_av-a121f90f388343dc48793cbc7eb899aba42e7664.tar.gz frameworks_av-a121f90f388343dc48793cbc7eb899aba42e7664.tar.bz2 |
audio policy: new setAudioPortConfig implementation
Rewrite setAudioPortConfig() to take advantage of the new
AudioPortConfig class.
The configuration is now checked against AudioPort capabilities
and stored in the AudioPortConfig.
Fix a bug where the config mask was not set properly when calling
setAudioPortConfig at the PatchPanel interface.
Remove debug log in IAudioPolicyService.
Bug: 14815883.
Change-Id: I7eb7683a96e049581c13f2a212486507883d008d
-rw-r--r-- | media/libmedia/IAudioPolicyService.cpp | 2 | ||||
-rw-r--r-- | services/audiopolicy/AudioPolicyManager.cpp | 264 | ||||
-rw-r--r-- | services/audiopolicy/AudioPolicyManager.h | 19 |
3 files changed, 209 insertions, 76 deletions
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index eee72c5..77d131b 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -421,7 +421,6 @@ public: status = (status_t)reply.readInt32(); *num_ports = (unsigned int)reply.readInt32(); } - ALOGI("listAudioPorts() status %d got *num_ports %d", status, *num_ports); if (status == NO_ERROR) { if (numPortsReq > *num_ports) { numPortsReq = *num_ports; @@ -840,7 +839,6 @@ status_t BnAudioPolicyService::onTransact( status_t status = listAudioPorts(role, type, &numPorts, ports, &generation); reply->writeInt32(status); reply->writeInt32(numPorts); - ALOGI("LIST_AUDIO_PORTS status %d got numPorts %d", status, numPorts); if (status == NO_ERROR) { if (numPortsReq > numPorts) { diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp index e4ff3b1..53e9eba 100644 --- a/services/audiopolicy/AudioPolicyManager.cpp +++ b/services/audiopolicy/AudioPolicyManager.cpp @@ -2035,27 +2035,24 @@ status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config * } ALOGV("setAudioPortConfig() on port handle %d", config->id); // Only support gain configuration for now - if (config->config_mask != AUDIO_PORT_CONFIG_GAIN || config->gain.index < 0) { - return BAD_VALUE; + if (config->config_mask != AUDIO_PORT_CONFIG_GAIN) { + return INVALID_OPERATION; } - sp<AudioPort> portDesc; - struct audio_port_config portConfig; + sp<AudioPortConfig> audioPortConfig; if (config->type == AUDIO_PORT_TYPE_MIX) { if (config->role == AUDIO_PORT_ROLE_SOURCE) { sp<AudioOutputDescriptor> outputDesc = getOutputFromId(config->id); if (outputDesc == NULL) { return BAD_VALUE; } - portDesc = outputDesc->mProfile; - outputDesc->toAudioPortConfig(&portConfig); + audioPortConfig = outputDesc; } else if (config->role == AUDIO_PORT_ROLE_SINK) { sp<AudioInputDescriptor> inputDesc = getInputFromId(config->id); if (inputDesc == NULL) { return BAD_VALUE; } - portDesc = inputDesc->mProfile; - inputDesc->toAudioPortConfig(&portConfig); + audioPortConfig = inputDesc; } else { return BAD_VALUE; } @@ -2071,47 +2068,22 @@ status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config * if (deviceDesc == NULL) { return BAD_VALUE; } - portDesc = deviceDesc; - deviceDesc->toAudioPortConfig(&portConfig); + audioPortConfig = deviceDesc; } else { return BAD_VALUE; } - if ((size_t)config->gain.index >= portDesc->mGains.size()) { - return INVALID_OPERATION; - } - const struct audio_gain *gain = &portDesc->mGains[config->gain.index]->mGain; - if ((config->gain.mode & ~gain->mode) != 0) { - return BAD_VALUE; - } - if ((config->gain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) { - if ((config->gain.values[0] < gain->min_value) || - (config->gain.values[0] > gain->max_value)) { - return BAD_VALUE; - } - } else { - if ((config->gain.channel_mask & ~gain->channel_mask) != 0) { - return BAD_VALUE; - } - size_t numValues = popcount(config->gain.channel_mask); - for (size_t i = 0; i < numValues; i++) { - if ((config->gain.values[i] < gain->min_value) || - (config->gain.values[i] > gain->max_value)) { - return BAD_VALUE; - } - } + struct audio_port_config backupConfig; + status_t status = audioPortConfig->applyAudioPortConfig(config, &backupConfig); + if (status == NO_ERROR) { + struct audio_port_config newConfig; + audioPortConfig->toAudioPortConfig(&newConfig, config); + status = mpClientInterface->setAudioPortConfig(&newConfig, 0); } - if ((config->gain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) { - if ((config->gain.ramp_duration_ms < gain->min_ramp_ms) || - (config->gain.ramp_duration_ms > gain->max_ramp_ms)) { - return BAD_VALUE; - } + if (status != NO_ERROR) { + audioPortConfig->applyAudioPortConfig(&backupConfig); } - portConfig.gain = config->gain; - - status_t status = mpClientInterface->setAudioPortConfig(&portConfig, 0); - return status; } @@ -4413,6 +4385,9 @@ AudioPolicyManager::AudioOutputDescriptor::AudioOutputDescriptor( mSamplingRate = profile->mSamplingRates[0]; mFormat = profile->mFormats[0]; mChannelMask = profile->mChannelMasks[0]; + if (profile->mGains.size() > 0) { + profile->mGains[0]->getDefaultConfig(&mGain); + } mFlags = profile->mFlags; } } @@ -4588,6 +4563,9 @@ AudioPolicyManager::AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfil mSamplingRate = profile->mSamplingRates[0]; mFormat = profile->mFormats[0]; mChannelMask = profile->mChannelMasks[0]; + if (profile->mGains.size() > 0) { + profile->mGains[0]->getDefaultConfig(&mGain); + } } else { mSamplingRate = 0; mFormat = AUDIO_FORMAT_DEFAULT; @@ -4897,6 +4875,15 @@ void AudioPolicyManager::HwModule::dump(int fd) // --- AudioPort class implementation + +AudioPolicyManager::AudioPort::AudioPort(const String8& name, audio_port_type_t type, + audio_port_role_t role, const sp<HwModule>& module) : + mName(name), mType(type), mRole(role), mModule(module) +{ + mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) || + ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK)); +} + void AudioPolicyManager::AudioPort::toAudioPort(struct audio_port *port) const { port->role = mRole; @@ -5032,18 +5019,17 @@ audio_gain_mode_t AudioPolicyManager::AudioPort::loadGainMode(char *name) return mode; } -void AudioPolicyManager::AudioPort::loadGain(cnode *root) +void AudioPolicyManager::AudioPort::loadGain(cnode *root, int index) { cnode *node = root->first_child; - sp<AudioGain> gain = new AudioGain(); + sp<AudioGain> gain = new AudioGain(index, mUseInChannelMask); 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)) { + if (mUseInChannelMask) { gain->mGain.channel_mask = (audio_channel_mask_t)stringToEnum(sInChannelsNameToEnumTable, ARRAY_SIZE(sInChannelsNameToEnumTable), @@ -5082,13 +5068,53 @@ void AudioPolicyManager::AudioPort::loadGain(cnode *root) void AudioPolicyManager::AudioPort::loadGains(cnode *root) { cnode *node = root->first_child; + int index = 0; while (node) { ALOGV("loadGains() loading gain %s", node->name); - loadGain(node); + loadGain(node, index++); node = node->next; } } +status_t AudioPolicyManager::AudioPort::checkSamplingRate(uint32_t samplingRate) const +{ + for (size_t i = 0; i < mSamplingRates.size(); i ++) { + if (mSamplingRates[i] == samplingRate) { + return NO_ERROR; + } + } + return BAD_VALUE; +} + +status_t AudioPolicyManager::AudioPort::checkChannelMask(audio_channel_mask_t channelMask) const +{ + for (size_t i = 0; i < mChannelMasks.size(); i ++) { + if (mChannelMasks[i] == channelMask) { + return NO_ERROR; + } + } + return BAD_VALUE; +} + +status_t AudioPolicyManager::AudioPort::checkFormat(audio_format_t format) const +{ + for (size_t i = 0; i < mFormats.size(); i ++) { + if (mFormats[i] == format) { + return NO_ERROR; + } + } + return BAD_VALUE; +} + +status_t AudioPolicyManager::AudioPort::checkGain(const struct audio_gain_config *gainConfig, + int index) const +{ + if (index < 0 || (size_t)index >= mGains.size()) { + return BAD_VALUE; + } + return mGains[index]->checkConfig(gainConfig); +} + void AudioPolicyManager::AudioPort::dump(int fd, int spaces) const { const size_t SIZE = 256; @@ -5147,11 +5173,72 @@ void AudioPolicyManager::AudioPort::dump(int fd, int spaces) const // --- AudioGain class implementation -AudioPolicyManager::AudioGain::AudioGain() +AudioPolicyManager::AudioGain::AudioGain(int index, bool useInChannelMask) { + mIndex = index; + mUseInChannelMask = useInChannelMask; memset(&mGain, 0, sizeof(struct audio_gain)); } +void AudioPolicyManager::AudioGain::getDefaultConfig(struct audio_gain_config *config) +{ + config->index = mIndex; + config->mode = mGain.mode; + config->channel_mask = mGain.channel_mask; + if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) { + config->values[0] = mGain.default_value; + } else { + uint32_t numValues; + if (mUseInChannelMask) { + numValues = audio_channel_count_from_in_mask(mGain.channel_mask); + } else { + numValues = audio_channel_count_from_out_mask(mGain.channel_mask); + } + for (size_t i = 0; i < numValues; i++) { + config->values[i] = mGain.default_value; + } + } + if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) { + config->ramp_duration_ms = mGain.min_ramp_ms; + } +} + +status_t AudioPolicyManager::AudioGain::checkConfig(const struct audio_gain_config *config) +{ + if ((config->mode & ~mGain.mode) != 0) { + return BAD_VALUE; + } + if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) { + if ((config->values[0] < mGain.min_value) || + (config->values[0] > mGain.max_value)) { + return BAD_VALUE; + } + } else { + if ((config->channel_mask & ~mGain.channel_mask) != 0) { + return BAD_VALUE; + } + uint32_t numValues; + if (mUseInChannelMask) { + numValues = audio_channel_count_from_in_mask(config->channel_mask); + } else { + numValues = audio_channel_count_from_out_mask(config->channel_mask); + } + for (size_t i = 0; i < numValues; i++) { + if ((config->values[i] < mGain.min_value) || + (config->values[i] > mGain.max_value)) { + return BAD_VALUE; + } + } + } + if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) { + if ((config->ramp_duration_ms < mGain.min_ramp_ms) || + (config->ramp_duration_ms > mGain.max_ramp_ms)) { + return BAD_VALUE; + } + } + return NO_ERROR; +} + void AudioPolicyManager::AudioGain::dump(int fd, int spaces, int index) const { const size_t SIZE = 256; @@ -5190,6 +5277,59 @@ AudioPolicyManager::AudioPortConfig::AudioPortConfig() mGain.index = -1; } +status_t AudioPolicyManager::AudioPortConfig::applyAudioPortConfig( + const struct audio_port_config *config, + struct audio_port_config *backupConfig) +{ + struct audio_port_config localBackupConfig; + status_t status = NO_ERROR; + + localBackupConfig.config_mask = config->config_mask; + toAudioPortConfig(&localBackupConfig); + + if (mAudioPort == 0) { + status = NO_INIT; + goto exit; + } + if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { + status = mAudioPort->checkSamplingRate(config->sample_rate); + if (status != NO_ERROR) { + goto exit; + } + mSamplingRate = config->sample_rate; + } + if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { + status = mAudioPort->checkChannelMask(config->channel_mask); + if (status != NO_ERROR) { + goto exit; + } + mChannelMask = config->channel_mask; + } + if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) { + status = mAudioPort->checkFormat(config->format); + if (status != NO_ERROR) { + goto exit; + } + mFormat = config->format; + } + if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) { + status = mAudioPort->checkGain(&config->gain, config->gain.index); + if (status != NO_ERROR) { + goto exit; + } + mGain = config->gain; + } + +exit: + if (status != NO_ERROR) { + applyAudioPortConfig(&localBackupConfig); + } + if (backupConfig != NULL) { + *backupConfig = localBackupConfig; + } + return status; +} + void AudioPolicyManager::AudioPortConfig::toAudioPortConfig( struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig) const @@ -5264,32 +5404,13 @@ bool AudioPolicyManager::IOProfile::isCompatibleProfile(audio_devices_t device, if ((mFlags & flags) != flags) { return false; } - size_t i; - for (i = 0; i < mSamplingRates.size(); i++) - { - if (mSamplingRates[i] == samplingRate) { - break; - } - } - if (i == mSamplingRates.size()) { + if (checkSamplingRate(samplingRate) != NO_ERROR) { return false; } - for (i = 0; i < mFormats.size(); i++) - { - if (mFormats[i] == format) { - break; - } - } - if (i == mFormats.size()) { + if (checkChannelMask(channelMask) != NO_ERROR) { return false; } - for (i = 0; i < mChannelMasks.size(); i++) - { - if (mChannelMasks[i] == channelMask) { - break; - } - } - if (i == mChannelMasks.size()) { + if (checkFormat(format) != NO_ERROR) { return false; } return true; @@ -5351,6 +5472,9 @@ AudioPolicyManager::DeviceDescriptor::DeviceDescriptor(const String8& name, audi mChannelMask(AUDIO_CHANNEL_NONE), mId(0) { mAudioPort = this; + if (mGains.size() > 0) { + mGains[0]->getDefaultConfig(&mGain); + } } bool AudioPolicyManager::DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h index db0da24..4327949 100644 --- a/services/audiopolicy/AudioPolicyManager.h +++ b/services/audiopolicy/AudioPolicyManager.h @@ -195,20 +195,23 @@ protected: class AudioGain: public RefBase { public: - AudioGain(); + AudioGain(int index, bool useInChannelMask); virtual ~AudioGain() {} void dump(int fd, int spaces, int index) const; + void getDefaultConfig(struct audio_gain_config *config); + status_t checkConfig(const struct audio_gain_config *config); + int mIndex; struct audio_gain mGain; + bool mUseInChannelMask; }; class AudioPort: public virtual RefBase { public: AudioPort(const String8& name, audio_port_type_t type, - audio_port_role_t role, const sp<HwModule>& module) : - mName(name), mType(type), mRole(role), mModule(module) {} + audio_port_role_t role, const sp<HwModule>& module); virtual ~AudioPort() {} virtual void toAudioPort(struct audio_port *port) const; @@ -219,14 +222,20 @@ protected: void loadInChannels(char *name); audio_gain_mode_t loadGainMode(char *name); - void loadGain(cnode *root); + void loadGain(cnode *root, int index); void loadGains(cnode *root); + status_t checkSamplingRate(uint32_t samplingRate) const; + status_t checkChannelMask(audio_channel_mask_t channelMask) const; + status_t checkFormat(audio_format_t format) const; + status_t checkGain(const struct audio_gain_config *gainConfig, int index) const; + void dump(int fd, int spaces) const; String8 mName; audio_port_type_t mType; audio_port_role_t mRole; + bool mUseInChannelMask; // 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 @@ -243,6 +252,8 @@ protected: AudioPortConfig(); virtual ~AudioPortConfig() {} + status_t applyAudioPortConfig(const struct audio_port_config *config, + struct audio_port_config *backupConfig = NULL); virtual void toAudioPortConfig(struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig = NULL) const = 0; sp<AudioPort> mAudioPort; |