summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--services/audioflinger/PatchPanel.cpp31
-rw-r--r--services/audiopolicy/AudioPolicyClientImpl.cpp7
-rw-r--r--services/audiopolicy/AudioPolicyInterface.h3
-rw-r--r--services/audiopolicy/AudioPolicyManager.cpp97
-rw-r--r--services/audiopolicy/AudioPolicyService.cpp29
-rw-r--r--services/audiopolicy/AudioPolicyService.h17
6 files changed, 176 insertions, 8 deletions
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 9680a9a..96a8127 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -404,13 +404,38 @@ status_t AudioFlinger::PatchPanel::listAudioPatches(unsigned int *num_patches __
}
/* Set audio port configuration */
-status_t AudioFlinger::PatchPanel::setAudioPortConfig(
- const struct audio_port_config *config __unused)
+status_t AudioFlinger::PatchPanel::setAudioPortConfig(const struct audio_port_config *config)
{
ALOGV("setAudioPortConfig");
+ status_t status = NO_ERROR;
+
+ sp<AudioFlinger> audioflinger = mAudioFlinger.promote();
+ if (audioflinger == 0) {
+ return NO_INIT;
+ }
+
+ audio_module_handle_t module;
+ if (config->type == AUDIO_PORT_TYPE_DEVICE) {
+ module = config->ext.device.hw_module;
+ } else {
+ module = config->ext.mix.hw_module;
+ }
+
+ ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(module);
+ if (index < 0) {
+ ALOGW("setAudioPortConfig() bad hw module %d", module);
+ return BAD_VALUE;
+ }
+
+ AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index);
+ if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) {
+ audio_hw_device_t *hwDevice = audioHwDevice->hwDevice();
+ return hwDevice->set_audio_port_config(hwDevice, config);
+ } else {
+ return INVALID_OPERATION;
+ }
return NO_ERROR;
}
-
}; // namespace android
diff --git a/services/audiopolicy/AudioPolicyClientImpl.cpp b/services/audiopolicy/AudioPolicyClientImpl.cpp
index cbab841..c322d92 100644
--- a/services/audiopolicy/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/AudioPolicyClientImpl.cpp
@@ -195,6 +195,13 @@ status_t AudioPolicyService::AudioPolicyClient::releaseAudioPatch(audio_patch_ha
return mAudioPolicyService->clientReleaseAudioPatch(handle, delayMs);
}
+status_t AudioPolicyService::AudioPolicyClient::setAudioPortConfig(
+ const struct audio_port_config *config,
+ int delayMs)
+{
+ return mAudioPolicyService->clientSetAudioPortConfig(config, delayMs);
+}
+
void AudioPolicyService::AudioPolicyClient::onAudioPortListUpdate()
{
mAudioPolicyService->onAudioPortListUpdate();
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index e0c7f61..c025a45 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -273,6 +273,9 @@ public:
virtual status_t releaseAudioPatch(audio_patch_handle_t handle,
int delayMs) = 0;
+ /* Set audio port configuration */
+ virtual status_t setAudioPortConfig(const struct audio_port_config *config, int delayMs) = 0;
+
virtual void onAudioPortListUpdate() = 0;
virtual void onAudioPatchListUpdate() = 0;
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 87d7771..318f5e5 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -2026,9 +2026,93 @@ status_t AudioPolicyManager::listAudioPatches(unsigned int *num_patches,
return NO_ERROR;
}
-status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *config __unused)
+status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *config)
{
- return NO_ERROR;
+ ALOGV("setAudioPortConfig()");
+
+ if (config == NULL) {
+ return BAD_VALUE;
+ }
+ 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;
+ }
+
+ sp<AudioPort> portDesc;
+ struct audio_port_config portConfig;
+ if (config->type == AUDIO_PORT_TYPE_MIX) {
+ if (config->role == AUDIO_PORT_ROLE_SOURCE) {
+ AudioOutputDescriptor *outputDesc = getOutputFromId(config->id);
+ if (outputDesc == NULL) {
+ return BAD_VALUE;
+ }
+ portDesc = outputDesc->mProfile;
+ outputDesc->toAudioPortConfig(&portConfig);
+ } else if (config->role == AUDIO_PORT_ROLE_SINK) {
+ AudioInputDescriptor *inputDesc = getInputFromId(config->id);
+ if (inputDesc == NULL) {
+ return BAD_VALUE;
+ }
+ portDesc = inputDesc->mProfile;
+ inputDesc->toAudioPortConfig(&portConfig);
+ } else {
+ return BAD_VALUE;
+ }
+ } else if (config->type == AUDIO_PORT_TYPE_DEVICE) {
+ sp<DeviceDescriptor> deviceDesc;
+ if (config->role == AUDIO_PORT_ROLE_SOURCE) {
+ deviceDesc = mAvailableInputDevices.getDeviceFromId(config->id);
+ } else if (config->role == AUDIO_PORT_ROLE_SINK) {
+ deviceDesc = mAvailableOutputDevices.getDeviceFromId(config->id);
+ } else {
+ return BAD_VALUE;
+ }
+ if (deviceDesc == NULL) {
+ return BAD_VALUE;
+ }
+ portDesc = deviceDesc;
+ deviceDesc->toAudioPortConfig(&portConfig);
+ } 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;
+ }
+ }
+ }
+ 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;
+ }
+ }
+
+ portConfig.gain = config->gain;
+
+ status_t status = mpClientInterface->setAudioPortConfig(&portConfig, 0);
+
+ return status;
}
void AudioPolicyManager::clearAudioPatches(uid_t uid)
@@ -4861,7 +4945,13 @@ void AudioPolicyManager::AudioPort::toAudioPort(struct audio_port *port) const
port->formats[i] = mFormats[i];
}
port->num_formats = i;
- port->num_gains = 0;
+
+ ALOGV("AudioPort::toAudioPort() num gains %d", mGains.size());
+
+ for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) {
+ port->gains[i] = mGains[i]->mGain;
+ }
+ port->num_gains = i;
}
@@ -5417,6 +5507,7 @@ void AudioPolicyManager::DeviceDescriptor::toAudioPortConfig(
void AudioPolicyManager::DeviceDescriptor::toAudioPort(struct audio_port *port) const
{
+ ALOGV("DeviceVector::toAudioPort() handle %d type %x", mId, mDeviceType);
AudioPort::toAudioPort(port);
port->id = mId;
toAudioPortConfig(&port->active_config);
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp
index f3d92ed..a2a0461 100644
--- a/services/audiopolicy/AudioPolicyService.cpp
+++ b/services/audiopolicy/AudioPolicyService.cpp
@@ -226,6 +226,12 @@ void AudioPolicyService::doOnAudioPatchListUpdate()
}
}
+status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_config *config,
+ int delayMs)
+{
+ return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs);
+}
+
AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service,
const sp<IAudioPolicyServiceClient>& client,
uid_t uid)
@@ -506,6 +512,16 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
svc->doOnAudioPatchListUpdate();
mLock.lock();
}break;
+ case SET_AUDIOPORT_CONFIG: {
+ SetAudioPortConfigData *data = (SetAudioPortConfigData *)command->mParam.get();
+ ALOGV("AudioCommandThread() processing set port config");
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0) {
+ command->mStatus = PERMISSION_DENIED;
+ } else {
+ command->mStatus = af->setAudioPortConfig(&data->mConfig);
+ }
+ } break;
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
@@ -716,6 +732,19 @@ void AudioPolicyService::AudioCommandThread::updateAudioPatchListCommand()
sendCommand(command);
}
+status_t AudioPolicyService::AudioCommandThread::setAudioPortConfigCommand(
+ const struct audio_port_config *config, int delayMs)
+{
+ sp<AudioCommand> command = new AudioCommand();
+ command->mCommand = SET_AUDIOPORT_CONFIG;
+ SetAudioPortConfigData *data = new SetAudioPortConfigData();
+ data->mConfig = *config;
+ command->mParam = data;
+ command->mWaitStatus = true;
+ ALOGV("AudioCommandThread() adding set port config delay %d", delayMs);
+ return sendCommand(command, delayMs);
+}
+
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h
index a579d1d..40f589b 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -166,6 +166,9 @@ public:
int delayMs);
status_t clientReleaseAudioPatch(audio_patch_handle_t handle,
int delayMs);
+ virtual status_t clientSetAudioPortConfig(const struct audio_port_config *config,
+ int delayMs);
+
void removeNotificationClient(uid_t uid);
void onAudioPortListUpdate();
void doOnAudioPortListUpdate();
@@ -200,7 +203,8 @@ private:
CREATE_AUDIO_PATCH,
RELEASE_AUDIO_PATCH,
UPDATE_AUDIOPORT_LIST,
- UPDATE_AUDIOPATCH_LIST
+ UPDATE_AUDIOPATCH_LIST,
+ SET_AUDIOPORT_CONFIG,
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -234,7 +238,8 @@ private:
int delayMs);
void updateAudioPortListCommand();
void updateAudioPatchListCommand();
-
+ status_t setAudioPortConfigCommand(const struct audio_port_config *config,
+ int delayMs);
void insertCommand_l(AudioCommand *command, int delayMs = 0);
private:
@@ -312,6 +317,11 @@ private:
audio_patch_handle_t mHandle;
};
+ class SetAudioPortConfigData : public AudioCommandData {
+ public:
+ struct audio_port_config mConfig;
+ };
+
Mutex mLock;
Condition mWaitWorkCV;
Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands
@@ -465,6 +475,9 @@ private:
virtual status_t releaseAudioPatch(audio_patch_handle_t handle,
int delayMs);
+ /* Set audio port configuration */
+ virtual status_t setAudioPortConfig(const struct audio_port_config *config, int delayMs);
+
virtual void onAudioPortListUpdate();
virtual void onAudioPatchListUpdate();