summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/libmedia/IAudioPolicyService.cpp2
-rw-r--r--services/audiopolicy/AudioPolicyManager.cpp264
-rw-r--r--services/audiopolicy/AudioPolicyManager.h19
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;