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.