audo policy: add effects to record clients

Add list of active effects on input streams and record
clients for further reporting in AudioRecordingConfiguration.

Bug: 111438757
Test: make and dumpsys
Change-Id: I1ae00d2431c80b053f67e2b780f368d5a4822b01
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 9f8b8c0..afd599f 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -23,6 +23,7 @@
 #include "AudioIODescriptorInterface.h"
 #include "AudioPort.h"
 #include "ClientDescriptor.h"
+#include "EffectDescriptor.h"
 
 namespace android {
 
@@ -62,7 +63,8 @@
     bool isSoundTrigger() const;
     void setClientActive(const sp<RecordClientDescriptor>& client, bool active);
     int32_t activeCount() { return mGlobalActiveCount; }
-
+    void trackEffectEnabled(const sp<EffectDescriptor> &effect, bool enabled);
+    EffectDescriptorCollection getEnabledEffects() const;
     // implementation of AudioIODescriptorInterface
     audio_config_base_t getConfig() const override;
     audio_patch_handle_t getPatchHandle() const override;
@@ -86,6 +88,9 @@
     RecordClientVector clientsList(bool activeOnly = false,
         audio_source_t source = AUDIO_SOURCE_DEFAULT, bool preferredDeviceOnly = false) const;
 
+    // implementation of ClientMapHandler<RecordClientDescriptor>
+    void addClient(const sp<RecordClientDescriptor> &client) override;
+
  private:
 
     void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client);
@@ -101,6 +106,7 @@
     SortedVector<audio_session_t> mPreemptedSessions;
     AudioPolicyClientInterface * const mClientInterface;
     int32_t mGlobalActiveCount = 0;  // non-client-specific activity ref count
+    EffectDescriptorCollection mEnabledEffects;
 };
 
 class AudioInputCollection :
@@ -126,6 +132,8 @@
 
     sp<AudioInputDescriptor> getInputForClient(audio_port_handle_t portId);
 
+    void trackEffectEnabled(const sp<EffectDescriptor> &effect, bool enabled);
+
     void dump(String8 *dst) const;
 };
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index 986d109..a187029 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -28,6 +28,7 @@
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 #include "AudioPatch.h"
+#include "EffectDescriptor.h"
 #include "RoutingStrategy.h"
 
 namespace android {
@@ -119,13 +120,15 @@
     void setAppState(app_state_t appState) { mAppState = appState; }
     app_state_t appState() { return mAppState; }
     bool isSilenced() const { return mAppState == APP_STATE_IDLE; }
+    void trackEffectEnabled(const sp<EffectDescriptor> &effect, bool enabled);
+    EffectDescriptorCollection getEnabledEffects() const { return mEnabledEffects; }
 
 private:
     const audio_source_t mSource;
     const audio_input_flags_t mFlags;
     const bool mIsSoundTrigger;
           app_state_t mAppState;
-
+    EffectDescriptorCollection mEnabledEffects;
 };
 
 class SourceClientDescriptor: public TrackClientDescriptor
@@ -172,7 +175,7 @@
     virtual ~ClientMapHandler() = default;
 
     // Track client management
-    void addClient(const sp<T> &client) {
+    virtual void addClient(const sp<T> &client) {
         const audio_port_handle_t portId = client->portId();
         LOG_ALWAYS_FATAL_IF(!mClients.emplace(portId, client).second,
                 "%s(%d): attempting to add client that already exists", __func__, portId);
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index 9fa7486..2dc33ab 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -25,12 +25,12 @@
 
 namespace android {
 
-
 class EffectDescriptor : public RefBase
 {
 public:
-    void dump(String8 *dst) const;
+    void dump(String8 *dst, int spaces = 0) const;
 
+    int mId;                // effect unique ID
     int mIo;                // io the effect is attached to
     routing_strategy mStrategy; // routing strategy the effect is associated to
     int mSession;               // audio session the effect is on
@@ -46,12 +46,14 @@
     status_t registerEffect(const effect_descriptor_t *desc, audio_io_handle_t io,
                             uint32_t strategy, int session, int id);
     status_t unregisterEffect(int id);
+    sp<EffectDescriptor> getEffect(int id) const;
     status_t setEffectEnabled(int id, bool enabled);
+    bool     isEffectEnabled(int id) const;
     uint32_t getMaxEffectsCpuLoad() const;
     uint32_t getMaxEffectsMemory() const;
-    bool isNonOffloadableEffectEnabled();
+    bool isNonOffloadableEffectEnabled() const;
 
-    void dump(String8 *dst) const;
+    void dump(String8 *dst, int spaces = 0, bool verbose = true) const;
 
 private:
     status_t setEffectEnabled(const sp<EffectDescriptor> &effectDesc, bool enabled);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 559274f..409e7d8 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -269,6 +269,16 @@
     }
 }
 
+void AudioInputDescriptor::addClient(const sp<RecordClientDescriptor> &client) {
+    ClientMapHandler<RecordClientDescriptor>::addClient(client);
+
+    for (size_t i = 0; i < mEnabledEffects.size(); i++) {
+        if (mEnabledEffects.valueAt(i)->mSession == client->session()) {
+            client->trackEffectEnabled(mEnabledEffects.valueAt(i), true);
+        }
+    }
+}
+
 void AudioInputDescriptor::setClientActive(const sp<RecordClientDescriptor>& client, bool active)
 {
     LOG_ALWAYS_FATAL_IF(getClient(client->portId()) == nullptr,
@@ -345,6 +355,33 @@
     return clients;
 }
 
+void AudioInputDescriptor::trackEffectEnabled(const sp<EffectDescriptor> &effect,
+                                              bool enabled)
+{
+    RecordClientVector clients = getClientsForSession((audio_session_t)effect->mSession);
+    for (const auto& client : clients) {
+        client->trackEffectEnabled(effect, enabled);
+    }
+
+    if (enabled) {
+        mEnabledEffects.replaceValueFor(effect->mId, effect);
+    } else {
+        mEnabledEffects.removeItem(effect->mId);
+    }
+}
+
+EffectDescriptorCollection AudioInputDescriptor::getEnabledEffects() const
+{
+    EffectDescriptorCollection enabledEffects;
+    // report effects for highest priority active source as applied to all clients
+    RecordClientVector clients =
+        clientsList(true /*activeOnly*/, source(), false /*preferredDeviceOnly*/);
+    if (clients.size() > 0) {
+        enabledEffects = clients[0]->getEnabledEffects();
+    }
+    return enabledEffects;
+}
+
 void AudioInputDescriptor::dump(String8 *dst) const
 {
     dst->appendFormat(" ID: %d\n", getId());
@@ -352,6 +389,7 @@
     dst->appendFormat(" Format: %d\n", mFormat);
     dst->appendFormat(" Channels: %08x\n", mChannelMask);
     dst->appendFormat(" Devices %08x\n", mDevice);
+    getEnabledEffects().dump(dst, 1 /*spaces*/, false /*verbose*/);
     dst->append(" AudioRecord Clients:\n");
     ClientMapHandler<RecordClientDescriptor>::dump(dst);
     dst->append("\n");
@@ -424,6 +462,17 @@
     return 0;
 }
 
+void AudioInputCollection::trackEffectEnabled(const sp<EffectDescriptor> &effect,
+                                            bool enabled)
+{
+    for (size_t i = 0; i < size(); i++) {
+        sp<AudioInputDescriptor> inputDesc = valueAt(i);
+        if (inputDesc->mIoHandle == effect->mIo) {
+            return inputDesc->trackEffectEnabled(effect, enabled);
+        }
+    }
+}
+
 void AudioInputCollection::dump(String8 *dst) const
 {
     dst->append("\nInputs dump:\n");
diff --git a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
index 815612d..82d64c9 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
@@ -63,10 +63,20 @@
     return ss.str();
 }
 
+void RecordClientDescriptor::trackEffectEnabled(const sp<EffectDescriptor> &effect, bool enabled)
+{
+    if (enabled) {
+        mEnabledEffects.replaceValueFor(effect->mId, effect);
+    } else {
+        mEnabledEffects.removeItem(effect->mId);
+    }
+}
+
 void RecordClientDescriptor::dump(String8 *dst, int spaces, int index) const
 {
     ClientDescriptor::dump(dst, spaces, index);
     dst->appendFormat("%*s- Source: %d flags: %08x\n", spaces, "", mSource, mFlags);
+    mEnabledEffects.dump(dst, spaces + 2 /*spaces*/, false /*verbose*/);
 }
 
 SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t uid,
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 8bbb798..40c49e7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -22,13 +22,13 @@
 
 namespace android {
 
-void EffectDescriptor::dump(String8 *dst) const
+void EffectDescriptor::dump(String8 *dst, int spaces) const
 {
-    dst->appendFormat(" I/O: %d\n", mIo);
-    dst->appendFormat(" Strategy: %d\n", mStrategy);
-    dst->appendFormat(" Session: %d\n", mSession);
-    dst->appendFormat(" Name: %s\n",  mDesc.name);
-    dst->appendFormat(" %s\n",  mEnabled ? "Enabled" : "Disabled");
+    dst->appendFormat("%*sI/O: %d\n", spaces, "", mIo);
+    dst->appendFormat("%*sStrategy: %d\n", spaces, "", mStrategy);
+    dst->appendFormat("%*sSession: %d\n", spaces, "", mSession);
+    dst->appendFormat("%*sName: %s\n", spaces, "",  mDesc.name);
+    dst->appendFormat("%*s%s\n", spaces, "",  mEnabled ? "Enabled" : "Disabled");
 }
 
 EffectDescriptorCollection::EffectDescriptorCollection() :
@@ -45,6 +45,11 @@
                                                     int session,
                                                     int id)
 {
+    if (getEffect(id) != nullptr) {
+        ALOGW("%s effect %s already registered", __FUNCTION__, desc->name);
+        return INVALID_OPERATION;
+    }
+
     if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
         ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
                 desc->name, desc->memoryUsage);
@@ -60,6 +65,7 @@
 
     sp<EffectDescriptor> effectDesc = new EffectDescriptor();
     memcpy (&effectDesc->mDesc, desc, sizeof(effect_descriptor_t));
+    effectDesc->mId = id;
     effectDesc->mIo = io;
     effectDesc->mStrategy = static_cast<routing_strategy>(strategy);
     effectDesc->mSession = session;
@@ -70,18 +76,23 @@
     return NO_ERROR;
 }
 
-status_t EffectDescriptorCollection::unregisterEffect(int id)
+sp<EffectDescriptor> EffectDescriptorCollection::getEffect(int id) const
 {
     ssize_t index = indexOfKey(id);
     if (index < 0) {
-        ALOGW("unregisterEffect() unknown effect ID %d", id);
+        return nullptr;
+    }
+    return valueAt(index);
+}
+
+status_t EffectDescriptorCollection::unregisterEffect(int id)
+{
+    sp<EffectDescriptor> effectDesc = getEffect(id);
+    if (effectDesc == nullptr) {
+        ALOGW("%s unknown effect ID %d", __FUNCTION__, id);
         return INVALID_OPERATION;
     }
 
-    sp<EffectDescriptor> effectDesc = valueAt(index);
-
-    setEffectEnabled(effectDesc, false);
-
     if (mTotalEffectsMemory < effectDesc->mDesc.memoryUsage) {
         ALOGW("unregisterEffect() memory %d too big for total %d",
                 effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
@@ -107,6 +118,14 @@
     return setEffectEnabled(valueAt(index), enabled);
 }
 
+bool EffectDescriptorCollection::isEffectEnabled(int id) const
+{
+    ssize_t index = indexOfKey(id);
+    if (index < 0) {
+        return false;
+    }
+    return valueAt(index)->mEnabled;
+}
 
 status_t EffectDescriptorCollection::setEffectEnabled(const sp<EffectDescriptor> &effectDesc,
                                                       bool enabled)
@@ -138,7 +157,7 @@
     return NO_ERROR;
 }
 
-bool EffectDescriptorCollection::isNonOffloadableEffectEnabled()
+bool EffectDescriptorCollection::isNonOffloadableEffectEnabled() const
 {
     for (size_t i = 0; i < size(); i++) {
         sp<EffectDescriptor> effectDesc = valueAt(i);
@@ -162,15 +181,21 @@
     return MAX_EFFECTS_MEMORY;
 }
 
-void EffectDescriptorCollection::dump(String8 *dst) const
+void EffectDescriptorCollection::dump(String8 *dst, int spaces, bool verbose) const
 {
-    dst->appendFormat(
-            "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB, Max memory used: %d KB\n",
-             (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory, mTotalEffectsMemoryMaxUsed);
-    dst->append("Registered effects:\n");
+    if (verbose) {
+        dst->appendFormat(
+            "\n%*sTotal Effects CPU: %f MIPS, "
+            "Total Effects memory: %d KB, Max memory used: %d KB\n",
+            spaces, "",
+            (float) mTotalEffectsCpuLoad / 10,
+            mTotalEffectsMemory,
+            mTotalEffectsMemoryMaxUsed);
+    }
+    dst->appendFormat("%*sEffects:\n", spaces, "");
     for (size_t i = 0; i < size(); i++) {
-        dst->appendFormat("- Effect %d dump:\n", keyAt(i));
-        valueAt(i)->dump(dst);
+        dst->appendFormat("%*s- Effect %d:\n", spaces, "", keyAt(i));
+        valueAt(i)->dump(dst, spaces + 2);
     }
 }
 
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 64a2b8a..3686f2d 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2423,6 +2423,33 @@
     return mEffects.registerEffect(desc, io, strategy, session, id);
 }
 
+status_t AudioPolicyManager::unregisterEffect(int id)
+{
+    if (mEffects.getEffect(id) == nullptr) {
+        return INVALID_OPERATION;
+    }
+
+    if (mEffects.isEffectEnabled(id)) {
+        ALOGW("%s effect %d enabled", __FUNCTION__, id);
+        setEffectEnabled(id, false);
+    }
+    return mEffects.unregisterEffect(id);
+}
+
+status_t AudioPolicyManager::setEffectEnabled(int id, bool enabled)
+{
+    sp<EffectDescriptor> effect = mEffects.getEffect(id);
+    if (effect == nullptr) {
+        return INVALID_OPERATION;
+    }
+
+    status_t status = mEffects.setEffectEnabled(id, enabled);
+    if (status == NO_ERROR) {
+        mInputs.trackEffectEnabled(effect, enabled);
+    }
+    return status;
+}
+
 bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
 {
     bool active = false;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 86993d4..35dd87c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -164,14 +164,8 @@
                                         uint32_t strategy,
                                         int session,
                                         int id);
-        virtual status_t unregisterEffect(int id)
-        {
-            return mEffects.unregisterEffect(id);
-        }
-        virtual status_t setEffectEnabled(int id, bool enabled)
-        {
-            return mEffects.setEffectEnabled(id, enabled);
-        }
+        virtual status_t unregisterEffect(int id);
+        virtual status_t setEffectEnabled(int id, bool enabled);
 
         virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
         // return whether a stream is playing remotely, override to change the definition of