audiopolicy: add Volume for attribute and callback native APIs
Change-Id: I259de42452d2802aa8dbd553f56040dea6995a93
Signed-off-by: François Gaffie <francois.gaffie@renault.com>
Bug: 124767636
Test: make
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 35adb72..0ce2513 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -792,6 +792,7 @@
int64_t token = IPCThreadState::self()->clearCallingIdentity();
ap->registerClient(apc);
ap->setAudioPortCallbacksEnabled(apc->isAudioPortCbEnabled());
+ ap->setAudioVolumeGroupCallbacksEnabled(apc->isAudioVolumeGroupCbEnabled());
IPCThreadState::self()->restoreCallingIdentity(token);
}
@@ -987,6 +988,38 @@
return aps->getStreamVolumeIndex(stream, index, device);
}
+status_t AudioSystem::setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->setVolumeIndexForAttributes(attr, index, device);
+}
+
+status_t AudioSystem::getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->getVolumeIndexForAttributes(attr, index, device);
+}
+
+status_t AudioSystem::getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->getMaxVolumeIndexForAttributes(attr, index);
+}
+
+status_t AudioSystem::getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->getMinVolumeIndexForAttributes(attr, index);
+}
+
uint32_t AudioSystem::getStrategyForStream(audio_stream_type_t stream)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
@@ -1190,6 +1223,38 @@
return (ret < 0) ? INVALID_OPERATION : NO_ERROR;
}
+status_t AudioSystem::addAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+
+ Mutex::Autolock _l(gLockAPS);
+ if (gAudioPolicyServiceClient == 0) {
+ return NO_INIT;
+ }
+ int ret = gAudioPolicyServiceClient->addAudioVolumeGroupCallback(callback);
+ if (ret == 1) {
+ aps->setAudioVolumeGroupCallbacksEnabled(true);
+ }
+ return (ret < 0) ? INVALID_OPERATION : NO_ERROR;
+}
+
+status_t AudioSystem::removeAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+
+ Mutex::Autolock _l(gLockAPS);
+ if (gAudioPolicyServiceClient == 0) {
+ return NO_INIT;
+ }
+ int ret = gAudioPolicyServiceClient->removeAudioVolumeGroupCallback(callback);
+ if (ret == 0) {
+ aps->setAudioVolumeGroupCallbacksEnabled(false);
+ }
+ return (ret < 0) ? INVALID_OPERATION : NO_ERROR;
+}
+
status_t AudioSystem::addAudioDeviceCallback(
const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
{
@@ -1498,6 +1563,47 @@
}
}
+// ----------------------------------------------------------------------------
+int AudioSystem::AudioPolicyServiceClient::addAudioVolumeGroupCallback(
+ const sp<AudioVolumeGroupCallback>& callback)
+{
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mAudioVolumeGroupCallback.size(); i++) {
+ if (mAudioVolumeGroupCallback[i] == callback) {
+ return -1;
+ }
+ }
+ mAudioVolumeGroupCallback.add(callback);
+ return mAudioVolumeGroupCallback.size();
+}
+
+int AudioSystem::AudioPolicyServiceClient::removeAudioVolumeGroupCallback(
+ const sp<AudioVolumeGroupCallback>& callback)
+{
+ Mutex::Autolock _l(mLock);
+ size_t i;
+ for (i = 0; i < mAudioVolumeGroupCallback.size(); i++) {
+ if (mAudioVolumeGroupCallback[i] == callback) {
+ break;
+ }
+ }
+ if (i == mAudioVolumeGroupCallback.size()) {
+ return -1;
+ }
+ mAudioVolumeGroupCallback.removeAt(i);
+ return mAudioVolumeGroupCallback.size();
+}
+
+void AudioSystem::AudioPolicyServiceClient::onAudioVolumeGroupChanged(volume_group_t group,
+ int flags)
+{
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mAudioVolumeGroupCallback.size(); i++) {
+ mAudioVolumeGroupCallback[i]->onAudioVolumeGroupChanged(group, flags);
+ }
+}
+// ----------------------------------------------------------------------------
+
void AudioSystem::AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate(
String8 regId, int32_t state)
{
@@ -1541,6 +1647,9 @@
for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) {
mAudioPortCallbacks[i]->onServiceDied();
}
+ for (size_t i = 0; i < mAudioVolumeGroupCallback.size(); i++) {
+ mAudioVolumeGroupCallback[i]->onServiceDied();
+ }
}
{
Mutex::Autolock _l(gLockAPS);
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index feb1317..3bac44f 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -51,6 +51,10 @@
INIT_STREAM_VOLUME,
SET_STREAM_VOLUME,
GET_STREAM_VOLUME,
+ SET_VOLUME_ATTRIBUTES,
+ GET_VOLUME_ATTRIBUTES,
+ GET_MIN_VOLUME_FOR_ATTRIBUTES,
+ GET_MAX_VOLUME_FOR_ATTRIBUTES,
GET_STRATEGY_FOR_STREAM,
GET_OUTPUT_FOR_EFFECT,
REGISTER_EFFECT,
@@ -78,6 +82,7 @@
START_AUDIO_SOURCE,
STOP_AUDIO_SOURCE,
SET_AUDIO_PORT_CALLBACK_ENABLED,
+ SET_AUDIO_VOLUME_GROUP_CALLBACK_ENABLED,
SET_MASTER_MONO,
GET_MASTER_MONO,
GET_STREAM_VOLUME_DB,
@@ -417,6 +422,70 @@
return static_cast <status_t> (reply.readInt32());
}
+ virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr, int index,
+ audio_devices_t device)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&attr, sizeof(audio_attributes_t));
+ data.writeInt32(index);
+ data.writeInt32(static_cast <uint32_t>(device));
+ status_t status = remote()->transact(SET_VOLUME_ATTRIBUTES, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast <status_t> (reply.readInt32());
+ }
+ virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr, int &index,
+ audio_devices_t device)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&attr, sizeof(audio_attributes_t));
+ data.writeInt32(static_cast <uint32_t>(device));
+ status_t status = remote()->transact(GET_VOLUME_ATTRIBUTES, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = static_cast <status_t> (reply.readInt32());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ index = reply.readInt32();
+ return NO_ERROR;
+ }
+ virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&attr, sizeof(audio_attributes_t));
+ status_t status = remote()->transact(GET_MIN_VOLUME_FOR_ATTRIBUTES, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = static_cast <status_t> (reply.readInt32());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ index = reply.readInt32();
+ return NO_ERROR;
+ }
+ virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(&attr, sizeof(audio_attributes_t));
+ status_t status = remote()->transact(GET_MAX_VOLUME_FOR_ATTRIBUTES, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = static_cast <status_t> (reply.readInt32());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ index = reply.readInt32();
+ return NO_ERROR;
+ }
virtual uint32_t getStrategyForStream(audio_stream_type_t stream)
{
Parcel data, reply;
@@ -694,6 +763,14 @@
remote()->transact(SET_AUDIO_PORT_CALLBACK_ENABLED, data, &reply);
}
+ virtual void setAudioVolumeGroupCallbacksEnabled(bool enabled)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(enabled ? 1 : 0);
+ remote()->transact(SET_AUDIO_VOLUME_GROUP_CALLBACK_ENABLED, data, &reply);
+ }
+
virtual status_t acquireSoundTriggerSession(audio_session_t *session,
audio_io_handle_t *ioHandle,
audio_devices_t *device)
@@ -1492,6 +1569,73 @@
return NO_ERROR;
} break;
+ case SET_VOLUME_ATTRIBUTES: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_attributes_t attributes = {};
+ status_t status = data.read(&attributes, sizeof(audio_attributes_t));
+ if (status != NO_ERROR) {
+ return status;
+ }
+ int index = data.readInt32();
+ audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
+
+ reply->writeInt32(static_cast <uint32_t>(setVolumeIndexForAttributes(attributes,
+ index, device)));
+ return NO_ERROR;
+ } break;
+
+ case GET_VOLUME_ATTRIBUTES: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_attributes_t attributes = {};
+ status_t status = data.read(&attributes, sizeof(audio_attributes_t));
+ if (status != NO_ERROR) {
+ return status;
+ }
+ audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
+
+ int index = 0;
+ status = getVolumeIndexForAttributes(attributes, index, device);
+ reply->writeInt32(static_cast <uint32_t>(status));
+ if (status == NO_ERROR) {
+ reply->writeInt32(index);
+ }
+ return NO_ERROR;
+ } break;
+
+ case GET_MIN_VOLUME_FOR_ATTRIBUTES: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_attributes_t attributes = {};
+ status_t status = data.read(&attributes, sizeof(audio_attributes_t));
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ int index = 0;
+ status = getMinVolumeIndexForAttributes(attributes, index);
+ reply->writeInt32(static_cast <uint32_t>(status));
+ if (status == NO_ERROR) {
+ reply->writeInt32(index);
+ }
+ return NO_ERROR;
+ } break;
+
+ case GET_MAX_VOLUME_FOR_ATTRIBUTES: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_attributes_t attributes = {};
+ status_t status = data.read(&attributes, sizeof(audio_attributes_t));
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ int index = 0;
+ status = getMaxVolumeIndexForAttributes(attributes, index);
+ reply->writeInt32(static_cast <uint32_t>(status));
+ if (status == NO_ERROR) {
+ reply->writeInt32(index);
+ }
+ return NO_ERROR;
+ } break;
+
case GET_DEVICES_FOR_STREAM: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_stream_type_t stream =
@@ -1740,6 +1884,12 @@
return NO_ERROR;
} break;
+ case SET_AUDIO_VOLUME_GROUP_CALLBACK_ENABLED: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ setAudioVolumeGroupCallbacksEnabled(data.readInt32() == 1);
+ return NO_ERROR;
+ } break;
+
case ACQUIRE_SOUNDTRIGGER_SESSION: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>(
diff --git a/media/libaudioclient/IAudioPolicyServiceClient.cpp b/media/libaudioclient/IAudioPolicyServiceClient.cpp
index 1f9eab7..52d8ccd 100644
--- a/media/libaudioclient/IAudioPolicyServiceClient.cpp
+++ b/media/libaudioclient/IAudioPolicyServiceClient.cpp
@@ -31,7 +31,8 @@
PORT_LIST_UPDATE = IBinder::FIRST_CALL_TRANSACTION,
PATCH_LIST_UPDATE,
MIX_STATE_UPDATE,
- RECORDING_CONFIGURATION_UPDATE
+ RECORDING_CONFIGURATION_UPDATE,
+ VOLUME_GROUP_CHANGED,
};
// ----------------------------------------------------------------------
@@ -108,6 +109,15 @@
remote()->transact(PATCH_LIST_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
}
+ void onAudioVolumeGroupChanged(volume_group_t group, int flags)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
+ data.writeUint32(group);
+ data.writeInt32(flags);
+ remote()->transact(VOLUME_GROUP_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+
void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state)
{
Parcel data, reply;
@@ -157,6 +167,13 @@
onAudioPatchListUpdate();
return NO_ERROR;
} break;
+ case VOLUME_GROUP_CHANGED: {
+ CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
+ volume_group_t group = static_cast<volume_group_t>(data.readUint32());
+ int flags = data.readInt32();
+ onAudioVolumeGroupChanged(group, flags);
+ return NO_ERROR;
+ } break;
case MIX_STATE_UPDATE: {
CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
String8 regId = data.readString8();
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 142d2bb..e64f285 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -264,6 +264,17 @@
int *index,
audio_devices_t device);
+ static status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device);
+ static status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device);
+
+ static status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
+
+ static status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
+
static uint32_t getStrategyForStream(audio_stream_type_t stream);
static audio_devices_t getDevicesForStream(audio_stream_type_t stream);
@@ -381,6 +392,21 @@
// ----------------------------------------------------------------------------
+ class AudioVolumeGroupCallback : public RefBase
+ {
+ public:
+
+ AudioVolumeGroupCallback() {}
+ virtual ~AudioVolumeGroupCallback() {}
+
+ virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags) = 0;
+ virtual void onServiceDied() = 0;
+
+ };
+
+ static status_t addAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback);
+ static status_t removeAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback);
+
class AudioPortCallback : public RefBase
{
public:
@@ -513,12 +539,17 @@
int removeAudioPortCallback(const sp<AudioPortCallback>& callback);
bool isAudioPortCbEnabled() const { return (mAudioPortCallbacks.size() != 0); }
+ int addAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback);
+ int removeAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback);
+ bool isAudioVolumeGroupCbEnabled() const { return (mAudioVolumeGroupCallback.size() != 0); }
+
// DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
// IAudioPolicyServiceClient
virtual void onAudioPortListUpdate();
virtual void onAudioPatchListUpdate();
+ virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags);
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
virtual void onRecordingConfigurationUpdate(int event,
const record_client_info_t *clientInfo,
@@ -532,6 +563,7 @@
private:
Mutex mLock;
Vector <sp <AudioPortCallback> > mAudioPortCallbacks;
+ Vector <sp <AudioVolumeGroupCallback> > mAudioVolumeGroupCallback;
};
static audio_io_handle_t getOutput(audio_stream_type_t stream);
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 800344d..35540f0 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -93,6 +93,17 @@
virtual status_t getStreamVolumeIndex(audio_stream_type_t stream,
int *index,
audio_devices_t device) = 0;
+
+ virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device) = 0;
+ virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device) = 0;
+ virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index) = 0;
+
+ virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index) = 0;
+
virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0;
virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream) = 0;
virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc) = 0;
@@ -160,6 +171,8 @@
virtual void setAudioPortCallbacksEnabled(bool enabled) = 0;
+ virtual void setAudioVolumeGroupCallbacksEnabled(bool enabled) = 0;
+
virtual status_t acquireSoundTriggerSession(audio_session_t *session,
audio_io_handle_t *ioHandle,
audio_devices_t *device) = 0;
diff --git a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
index b3c0381..79008c3 100644
--- a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
+++ b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
@@ -23,6 +23,8 @@
#include <binder/IInterface.h>
#include <system/audio.h>
#include <system/audio_effect.h>
+#include <media/AudioPolicy.h>
+#include <media/AudioVolumeGroup.h>
namespace android {
@@ -45,6 +47,8 @@
public:
DECLARE_META_INTERFACE(AudioPolicyServiceClient);
+ // Notifies a change of volume group
+ virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags) = 0;
// Notifies a change of audio port configuration.
virtual void onAudioPortListUpdate() = 0;
// Notifies a change of audio patch configuration.
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 9b00a4d..d61188f 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -159,6 +159,19 @@
int *index,
audio_devices_t device) = 0;
+ virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device) = 0;
+ virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device) = 0;
+
+ virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index) = 0;
+
+ virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index) = 0;
+
// return the strategy corresponding to a given stream type
virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0;
@@ -347,6 +360,8 @@
virtual void onAudioPatchListUpdate() = 0;
+ virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags) = 0;
+
virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) = 0;
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 4540c4d..92aa189 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2498,6 +2498,107 @@
return NO_ERROR;
}
+status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device)
+{
+ // Get Volume group matching the Audio Attributes
+ auto volumeGroup = mEngine->getVolumeGroupForAttributes(attr);
+ if (volumeGroup == VOLUME_GROUP_NONE) {
+ ALOGD("%s: could not find group matching with %s", __FUNCTION__, toString(attr).c_str());
+ return BAD_VALUE;
+ }
+ ALOGD("%s: FOUND group %d matching with %s", __FUNCTION__, volumeGroup, toString(attr).c_str());
+ return setVolumeGroupIndex(getVolumeCurves(attr), volumeGroup, index, device, attr);
+}
+
+status_t AudioPolicyManager::setVolumeGroupIndex(IVolumeCurves &curves, volume_group_t group,
+ int index,
+ audio_devices_t device,
+ const audio_attributes_t /*attributes*/)
+{
+ ALOGVV("%s: group=%d", __func__, group);
+ status_t status = NO_ERROR;
+ setVolumeCurveIndex(group, index, device, curves);
+ // update volume on all outputs and streams matching the following:
+ // - The requested stream (or a stream matching for volume control) is active on the output
+ // - The device (or devices) selected by the engine for this stream includes
+ // the requested device
+ // - For non default requested device, currently selected device on the output is either the
+ // requested device or one of the devices selected by the engine for this stream
+ // - For default requested device (AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME), apply volume only if
+ // no specific device volume value exists for currently selected device.
+ // @TODO
+ mpClientInterface->onAudioVolumeGroupChanged(group, 0 /*flags*/);
+ return status;
+}
+
+status_t AudioPolicyManager::setVolumeCurveIndex(volume_group_t volumeGroup,
+ int index,
+ audio_devices_t device,
+ IVolumeCurves &volumeCurves)
+{
+ // VOICE_CALL stream has minVolumeIndex > 0 but can be muted directly by an
+ // app that has MODIFY_PHONE_STATE permission.
+ // If voice is member of the volume group, it will contaminate all the member of this group
+ auto streams = mEngine->getStreamTypesForVolumeGroup(volumeGroup);
+ if (((index < volumeCurves.getVolumeIndexMin()) && !(hasVoiceStream(streams) && index == 0)) ||
+ (index > volumeCurves.getVolumeIndexMax())) {
+ ALOGD("%s: wrong index %d min=%d max=%d", __FUNCTION__, index,
+ volumeCurves.getVolumeIndexMin(), volumeCurves.getVolumeIndexMax());
+ return BAD_VALUE;
+ }
+ if (!audio_is_output_device(device)) {
+ return BAD_VALUE;
+ }
+
+ // Force max volume if stream cannot be muted
+ if (!volumeCurves.canBeMuted()) index = volumeCurves.getVolumeIndexMax();
+
+ ALOGD("%s device %08x, index %d", __FUNCTION__ , device, index);
+ volumeCurves.addCurrentVolumeIndex(device, index);
+ return NO_ERROR;
+}
+
+status_t AudioPolicyManager::getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device)
+{
+ // if device is AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, return volume for device selected for this
+ // stream by the engine.
+ if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
+ device = mEngine->getOutputDevicesForAttributes(attr, nullptr, true /*fromCache*/).types();
+ }
+ return getVolumeIndex(getVolumeCurves(attr), index, device);
+}
+
+status_t AudioPolicyManager::getVolumeIndex(const IVolumeCurves &curves,
+ int &index,
+ audio_devices_t device) const
+{
+ if (!audio_is_output_device(device)) {
+ return BAD_VALUE;
+ }
+ device = Volume::getDeviceForVolume(device);
+ index = curves.getVolumeIndex(device);
+ ALOGV("%s: device %08x index %d", __FUNCTION__, device, index);
+ return NO_ERROR;
+}
+
+status_t AudioPolicyManager::getMinVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index)
+{
+ index = getVolumeCurves(attr).getVolumeIndexMin();
+ return NO_ERROR;
+}
+
+status_t AudioPolicyManager::getMaxVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index)
+{
+ index = getVolumeCurves(attr).getVolumeIndexMax();
+ return NO_ERROR;
+}
+
audio_io_handle_t AudioPolicyManager::selectOutputForMusicEffects()
{
// select one output among several suitable for global effects.
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 9fe8d1d..641a03a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -161,6 +161,27 @@
int *index,
audio_devices_t device);
+ virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device);
+ virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device);
+ virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
+
+ virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
+
+ status_t setVolumeGroupIndex(IVolumeCurves &volumeCurves, volume_group_t group, int index,
+ audio_devices_t device, const audio_attributes_t attributes);
+
+ status_t setVolumeCurveIndex(volume_group_t volumeGroup,
+ int index,
+ audio_devices_t device,
+ IVolumeCurves &volumeCurves);
+
+ status_t getVolumeIndex(const IVolumeCurves &curves, int &index,
+ audio_devices_t device) const;
+
// return the strategy corresponding to a given stream type
virtual uint32_t getStrategyForStream(audio_stream_type_t stream)
{
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index d826192..5748334 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -222,6 +222,12 @@
clientConfig, clientEffects, deviceConfig, effects, patchHandle, source);
}
+void AudioPolicyService::AudioPolicyClient::onAudioVolumeGroupChanged(volume_group_t group,
+ int flags)
+{
+ mAudioPolicyService->onAudioVolumeGroupChanged(group, flags);
+}
+
audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId(audio_unique_id_use_t use)
{
return AudioSystem::newAudioUniqueId(use);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index c19016f..a1b6b0f 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -689,6 +689,53 @@
device);
}
+status_t AudioPolicyService::setVolumeIndexForAttributes(const audio_attributes_t &attributes,
+ int index, audio_devices_t device)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
+ return mAudioPolicyManager->setVolumeIndexForAttributes(attributes, index, device);
+}
+
+status_t AudioPolicyService::getVolumeIndexForAttributes(const audio_attributes_t &attributes,
+ int &index, audio_devices_t device)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
+ return mAudioPolicyManager->getVolumeIndexForAttributes(attributes, index, device);
+}
+
+status_t AudioPolicyService::getMinVolumeIndexForAttributes(const audio_attributes_t &attributes,
+ int &index)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
+ return mAudioPolicyManager->getMinVolumeIndexForAttributes(attributes, index);
+}
+
+status_t AudioPolicyService::getMaxVolumeIndexForAttributes(const audio_attributes_t &attributes,
+ int &index)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
+ return mAudioPolicyManager->getMaxVolumeIndexForAttributes(attributes, index);
+}
+
uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream)
{
if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 76ac191..cf9cf71 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -150,6 +150,20 @@
mNotificationClients.valueFor(token)->setAudioPortCallbacksEnabled(enabled);
}
+void AudioPolicyService::setAudioVolumeGroupCallbacksEnabled(bool enabled)
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ pid_t pid = IPCThreadState::self()->getCallingPid();
+ int64_t token = ((int64_t)uid<<32) | pid;
+
+ if (mNotificationClients.indexOfKey(token) < 0) {
+ return;
+ }
+ mNotificationClients.valueFor(token)->setAudioVolumeGroupCallbacksEnabled(enabled);
+}
+
// removeNotificationClient() is called when the client process dies.
void AudioPolicyService::removeNotificationClient(uid_t uid, pid_t pid)
{
@@ -200,6 +214,19 @@
}
}
+void AudioPolicyService::onAudioVolumeGroupChanged(volume_group_t group, int flags)
+{
+ mOutputCommandThread->changeAudioVolumeGroupCommand(group, flags);
+}
+
+void AudioPolicyService::doOnAudioVolumeGroupChanged(volume_group_t group, int flags)
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+ for (size_t i = 0; i < mNotificationClients.size(); i++) {
+ mNotificationClients.valueAt(i)->onAudioVolumeGroupChanged(group, flags);
+ }
+}
+
void AudioPolicyService::onDynamicPolicyMixStateUpdate(const String8& regId, int32_t state)
{
ALOGV("AudioPolicyService::onDynamicPolicyMixStateUpdate(%s, %d)",
@@ -270,7 +297,7 @@
uid_t uid,
pid_t pid)
: mService(service), mUid(uid), mPid(pid), mAudioPolicyServiceClient(client),
- mAudioPortCallbacksEnabled(false)
+ mAudioPortCallbacksEnabled(false), mAudioVolumeGroupCallbacksEnabled(false)
{
}
@@ -301,6 +328,15 @@
}
}
+void AudioPolicyService::NotificationClient::onAudioVolumeGroupChanged(volume_group_t group,
+ int flags)
+{
+ if (mAudioPolicyServiceClient != 0 && mAudioVolumeGroupCallbacksEnabled) {
+ mAudioPolicyServiceClient->onAudioVolumeGroupChanged(group, flags);
+ }
+}
+
+
void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate(
const String8& regId, int32_t state)
{
@@ -330,6 +366,10 @@
mAudioPortCallbacksEnabled = enabled;
}
+void AudioPolicyService::NotificationClient::setAudioVolumeGroupCallbacksEnabled(bool enabled)
+{
+ mAudioVolumeGroupCallbacksEnabled = enabled;
+}
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
@@ -1058,6 +1098,18 @@
svc->doOnAudioPatchListUpdate();
mLock.lock();
}break;
+ case CHANGED_AUDIOVOLUMEGROUP: {
+ AudioVolumeGroupData *data =
+ static_cast<AudioVolumeGroupData *>(command->mParam.get());
+ ALOGV("AudioCommandThread() processing update audio volume group");
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnAudioVolumeGroupChanged(data->mGroup, data->mFlags);
+ mLock.lock();
+ }break;
case SET_AUDIOPORT_CONFIG: {
SetAudioPortConfigData *data = (SetAudioPortConfigData *)command->mParam.get();
ALOGV("AudioCommandThread() processing set port config");
@@ -1302,6 +1354,19 @@
sendCommand(command);
}
+void AudioPolicyService::AudioCommandThread::changeAudioVolumeGroupCommand(volume_group_t group,
+ int flags)
+{
+ sp<AudioCommand>command = new AudioCommand();
+ command->mCommand = CHANGED_AUDIOVOLUMEGROUP;
+ AudioVolumeGroupData *data= new AudioVolumeGroupData();
+ data->mGroup = group;
+ data->mFlags = flags;
+ command->mParam = data;
+ ALOGV("AudioCommandThread() adding audio volume group changed");
+ sendCommand(command);
+}
+
status_t AudioPolicyService::AudioCommandThread::setAudioPortConfigCommand(
const struct audio_port_config *config, int delayMs)
{
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index e19b4e5..5888841 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -111,6 +111,17 @@
int *index,
audio_devices_t device);
+ virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int index,
+ audio_devices_t device);
+ virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index,
+ audio_devices_t device);
+ virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index);
+ virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr,
+ int &index);
+
virtual uint32_t getStrategyForStream(audio_stream_type_t stream);
virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream);
@@ -192,6 +203,8 @@
virtual void setAudioPortCallbacksEnabled(bool enabled);
+ virtual void setAudioVolumeGroupCallbacksEnabled(bool enabled);
+
virtual status_t acquireSoundTriggerSession(audio_session_t *session,
audio_io_handle_t *ioHandle,
audio_devices_t *device);
@@ -275,6 +288,9 @@
audio_patch_handle_t patchHandle,
audio_source_t source);
+ void onAudioVolumeGroupChanged(volume_group_t group, int flags);
+ void doOnAudioVolumeGroupChanged(volume_group_t group, int flags);
+
private:
AudioPolicyService() ANDROID_API;
virtual ~AudioPolicyService();
@@ -404,6 +420,7 @@
RELEASE_AUDIO_PATCH,
UPDATE_AUDIOPORT_LIST,
UPDATE_AUDIOPATCH_LIST,
+ CHANGED_AUDIOVOLUMEGROUP,
SET_AUDIOPORT_CONFIG,
DYN_POLICY_MIX_STATE_UPDATE,
RECORDING_CONFIGURATION_UPDATE
@@ -435,6 +452,7 @@
int delayMs);
void updateAudioPortListCommand();
void updateAudioPatchListCommand();
+ void changeAudioVolumeGroupCommand(volume_group_t group, int flags);
status_t setAudioPortConfigCommand(const struct audio_port_config *config,
int delayMs);
void dynamicPolicyMixStateUpdateCommand(const String8& regId,
@@ -516,6 +534,12 @@
audio_patch_handle_t mHandle;
};
+ class AudioVolumeGroupData : public AudioCommandData {
+ public:
+ volume_group_t mGroup;
+ int mFlags;
+ };
+
class SetAudioPortConfigData : public AudioCommandData {
public:
struct audio_port_config mConfig;
@@ -648,6 +672,8 @@
audio_patch_handle_t patchHandle,
audio_source_t source);
+ virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags);
+
virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
private:
@@ -666,6 +692,7 @@
void onAudioPatchListUpdate();
void onDynamicPolicyMixStateUpdate(const String8& regId,
int32_t state);
+ void onAudioVolumeGroupChanged(volume_group_t group, int flags);
void onRecordingConfigurationUpdate(
int event,
const record_client_info_t *clientInfo,
@@ -676,6 +703,7 @@
audio_patch_handle_t patchHandle,
audio_source_t source);
void setAudioPortCallbacksEnabled(bool enabled);
+ void setAudioVolumeGroupCallbacksEnabled(bool enabled);
uid_t uid() {
return mUid;
@@ -693,6 +721,7 @@
const pid_t mPid;
const sp<IAudioPolicyServiceClient> mAudioPolicyServiceClient;
bool mAudioPortCallbacksEnabled;
+ bool mAudioVolumeGroupCallbacksEnabled;
};
class AudioClient : public virtual RefBase {
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index 6ae354b..8854eb2 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -73,6 +73,7 @@
int /*delayMs*/) override { return NO_INIT; }
void onAudioPortListUpdate() override { }
void onAudioPatchListUpdate() override { }
+ void onAudioVolumeGroupChanged(volume_group_t /*group*/, int /*flags*/) override { }
audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t /*use*/) override { return 0; }
void onDynamicPolicyMixStateUpdate(String8 /*regId*/, int32_t /*state*/) override { }
void onRecordingConfigurationUpdate(int event __unused,