Merge "Add effect proxy shared capability and parameters clamping" into main
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index c7c6536..ac3975e 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -23,6 +23,7 @@
 
 #include <fmq/AidlMessageQueue.h>
 #include <system/audio_aidl_utils.h>
+#include <system/audio_effects/aidl_effects_utils.h>
 #include <utils/Log.h>
 
 #include "EffectProxy.h"
@@ -41,7 +42,8 @@
 
 EffectProxy::EffectProxy(const AudioUuid& uuid, const std::vector<Descriptor>& descriptors,
                          const std::shared_ptr<IFactory>& factory)
-    : mDescriptorCommon(buildDescriptorCommon(uuid, descriptors)),
+    : mSharedCapability(buildDescriptorCapability(descriptors)),
+      mDescriptorCommon(buildDescriptorCommon(uuid, descriptors)),
       mSubEffects(
               [](const std::vector<Descriptor>& descs, const std::shared_ptr<IFactory>& factory) {
                   std::vector<SubEffect> subEffects;
@@ -163,6 +165,7 @@
 
 ndk::ScopedAStatus EffectProxy::getDescriptor(Descriptor* desc) {
     *desc = mSubEffects[mActiveSubIdx].descriptor;
+    desc->capability = mSharedCapability;
     desc->common = mDescriptorCommon;
     return ndk::ScopedAStatus::ok();
 }
@@ -182,6 +185,7 @@
     }
 
     desc->common = buildDescriptorCommon(uuid, subEffectDescs);
+    desc->capability = buildDescriptorCapability(subEffectDescs);
     return ndk::ScopedAStatus::ok();
 }
 
@@ -216,6 +220,20 @@
     return swCommon;
 }
 
+// Build a shared Descriptor capability with all sub-effects.
+Capability EffectProxy::buildDescriptorCapability(const std::vector<Descriptor>& subEffectDescs) {
+    std::optional<Capability> cap = subEffectDescs[0].capability;
+    for (size_t i = 1; i < subEffectDescs.size(); i++) {
+        cap = findSharedCapability(cap.value(), subEffectDescs[i].capability);
+        if (!cap) {
+            ALOGE("%s failed to find the shared capability at %zu", __func__, i);
+            return subEffectDescs[0].capability;
+        }
+    }
+
+    return cap.value();
+}
+
 // Handle with active sub-effect first, only send to other sub-effects when success
 ndk::ScopedAStatus EffectProxy::command(CommandId id) {
     return runWithActiveSubEffectThenOthers(
@@ -323,6 +341,8 @@
     prefixSpace += " ";
     base::StringAppendF(&ss, "%sDescriptorCommon: %s\n", prefixSpace.c_str(),
                         mDescriptorCommon.toString().c_str());
+    base::StringAppendF(&ss, "%sDescriptorCapability: %s\n", prefixSpace.c_str(),
+                        mSharedCapability.toString().c_str());
     base::StringAppendF(&ss, "%sActiveSubIdx: %zu\n", prefixSpace.c_str(), mActiveSubIdx);
     base::StringAppendF(&ss, "%sAllSubEffects:\n", prefixSpace.c_str());
     for (size_t i = 0; i < mSubEffects.size(); i++) {
diff --git a/media/libaudiohal/impl/EffectProxy.h b/media/libaudiohal/impl/EffectProxy.h
index 9b9e8f1..6736104 100644
--- a/media/libaudiohal/impl/EffectProxy.h
+++ b/media/libaudiohal/impl/EffectProxy.h
@@ -108,6 +108,8 @@
     std::string toString(size_t indent = 0) const;
 
   private:
+    // The shared capability of all sub-effects
+    const ::aidl::android::hardware::audio::effect::Capability mSharedCapability;
     // Proxy descriptor common part, copy from one sub-effect, and update the implementation UUID to
     // proxy UUID, proxy descriptor capability part comes from the active sub-effect capability
     const ::aidl::android::hardware::audio::effect::Descriptor::Common mDescriptorCommon;
@@ -146,6 +148,11 @@
             const std::vector<::aidl::android::hardware::audio::effect::Descriptor>&
                     subEffectDescs);
 
+    // build a shared capability with all sub-effect descriptors
+    static ::aidl::android::hardware::audio::effect::Capability buildDescriptorCapability(
+            const std::vector<::aidl::android::hardware::audio::effect::Descriptor>&
+                    subEffectDescs);
+
     // close and release all sub-effects
     ~EffectProxy();
 };
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
index f77c093..711050d 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
@@ -25,6 +25,7 @@
 #include <media/AidlConversionNdk.h>
 #include <media/AidlConversionEffect.h>
 #include <system/audio_effect.h>
+#include <system/audio_effects/aidl_effects_utils.h>
 #include <system/audio_effects/effect_dynamicsprocessing.h>
 #include <Utils.h>
 #include <utils/Log.h>
@@ -38,8 +39,10 @@
 using ::aidl::android::getParameterSpecificField;
 using ::aidl::android::aidl_utils::statusTFromBinderStatus;
 using ::aidl::android::hardware::audio::effect::Capability;
+using ::aidl::android::hardware::audio::effect::clampParameter;
 using ::aidl::android::hardware::audio::effect::DynamicsProcessing;
 using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Range;
 using ::aidl::android::hardware::audio::effect::toString;
 using ::aidl::android::hardware::audio::effect::VendorExtension;
 using ::android::status_t;
@@ -126,7 +129,14 @@
         }
     }
 
-    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+    std::optional<Parameter> clamped =
+            clampParameter<Range::dynamicsProcessing, Parameter::Specific::dynamicsProcessing>(
+                    aidlParam, getDescriptor().capability);
+    if (!clamped) {
+        ALOGE("%s failed to clamp parameters: %s", __func__, aidlParam.toString().c_str());
+        return BAD_VALUE;
+    }
+    return statusTFromBinderStatus(mEffect->setParameter(clamped.value()));
 }
 
 status_t AidlConversionDp::getParameter(EffectParamWriter& param) {