Volume : Add minimum and maximum capabilities for params.

Bug: 263416041
Test: atest VtsHalVolumeTargetTest

Change-Id: Iea1253d9bfb049916f8f60e675eacf8e9040d087
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Volume.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Volume.aidl
index ccd32e8..6259cfb 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Volume.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Volume.aidl
@@ -37,9 +37,6 @@
   android.hardware.audio.effect.VendorExtension vendor;
   int levelDb;
   boolean mute;
-  // TODO(b/263416041) Move to Capability
-  const int MIN_LEVEL_DB = -9600;
-  const int MAX_LEVEL_DB = 0;
   @VintfStability
   union Id {
     int vendorExtensionTag;
@@ -48,6 +45,7 @@
   @VintfStability
   parcelable Capability {
     android.hardware.audio.effect.VendorExtension extension;
-    int maxLevel;
+    int minLevelDb;
+    int maxLevelDb;
   }
 }
diff --git a/audio/aidl/android/hardware/audio/effect/Volume.aidl b/audio/aidl/android/hardware/audio/effect/Volume.aidl
index a9f8371..5033881 100644
--- a/audio/aidl/android/hardware/audio/effect/Volume.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Volume.aidl
@@ -52,25 +52,18 @@
         VendorExtension extension;
 
         /**
-         * Volume strength supported in dB.
+         * Minimum Volume level supported in dB.
          */
-        int maxLevel;
+        int minLevelDb;
+
+        /**
+         * Maximum Volume level supported in dB.
+         */
+        int maxLevelDb;
     }
 
-    // TODO(b/263416041) Move to Capability
     /**
-     * Minimal level in dB.
-     */
-    const int MIN_LEVEL_DB = -9600;
-
-    /**
-     * Maximum level in dB.
-     */
-    const int MAX_LEVEL_DB = 0;
-
-    /**
-    /**
-     * Current level in dB.
+     * Current level in dB with supported minimum and maximum level specified in capability.
      */
     int levelDb;
     /**
diff --git a/audio/aidl/default/volume/VolumeSw.cpp b/audio/aidl/default/volume/VolumeSw.cpp
index 24e1e1d..64301dc 100644
--- a/audio/aidl/default/volume/VolumeSw.cpp
+++ b/audio/aidl/default/volume/VolumeSw.cpp
@@ -60,7 +60,7 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string VolumeSw::kEffectName = "VolumeSw";
-const Volume::Capability VolumeSw::kCapability = {.maxLevel = Volume::MAX_LEVEL_DB};
+const Volume::Capability VolumeSw::kCapability = {.minLevelDb = -9600, .maxLevelDb = 0};
 const Descriptor VolumeSw::kDescriptor = {
         .common = {.id = {.type = kVolumeTypeUUID,
                           .uuid = kVolumeSwImplUUID,
@@ -176,4 +176,20 @@
     return {STATUS_OK, samples, samples};
 }
 
+RetCode VolumeSwContext::setVolLevel(int level) {
+    if (level < VolumeSw::kCapability.minLevelDb || level > VolumeSw::kCapability.maxLevelDb) {
+        LOG(ERROR) << __func__ << " invalid level " << level;
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+    // TODO : Add implementation to apply new level
+    mLevel = level;
+    return RetCode::SUCCESS;
+}
+
+RetCode VolumeSwContext::setVolMute(bool mute) {
+    // TODO : Add implementation to modify mute
+    mMute = mute;
+    return RetCode::SUCCESS;
+}
+
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/volume/VolumeSw.h b/audio/aidl/default/volume/VolumeSw.h
index a101c59..b6f6077 100644
--- a/audio/aidl/default/volume/VolumeSw.h
+++ b/audio/aidl/default/volume/VolumeSw.h
@@ -33,23 +33,11 @@
         LOG(DEBUG) << __func__;
     }
 
-    RetCode setVolLevel(int level) {
-        if (level < Volume::MIN_LEVEL_DB || level > Volume::MAX_LEVEL_DB) {
-            LOG(ERROR) << __func__ << " invalid level " << level;
-            return RetCode::ERROR_ILLEGAL_PARAMETER;
-        }
-        // TODO : Add implementation to apply new level
-        mLevel = level;
-        return RetCode::SUCCESS;
-    }
+    RetCode setVolLevel(int level);
 
     int getVolLevel() const { return mLevel; }
 
-    RetCode setVolMute(bool mute) {
-        // TODO : Add implementation to modify mute
-        mMute = mute;
-        return RetCode::SUCCESS;
-    }
+    RetCode setVolMute(bool mute);
 
     bool getVolMute() const { return mMute; }
 
diff --git a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
index 3e82854..34625e7 100644
--- a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
@@ -34,17 +34,14 @@
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
  * VtsAudioEffectTargetTest.
  */
-enum ParamName { PARAM_INSTANCE_NAME, PARAM_LEVEL_DB, PARAM_MUTE };
+enum ParamName { PARAM_INSTANCE_NAME, PARAM_LEVEL, PARAM_MUTE };
 using VolumeParamTestParam =
         std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int, bool>;
 
-const std::vector<int> kLevelValues = {Volume::MIN_LEVEL_DB - 1, Volume::MIN_LEVEL_DB, -100,
-                                       Volume::MAX_LEVEL_DB, Volume::MAX_LEVEL_DB + 1};
-
 class VolumeParamTest : public ::testing::TestWithParam<VolumeParamTestParam>, public EffectHelper {
   public:
     VolumeParamTest()
-        : mParamLevel(std::get<PARAM_LEVEL_DB>(GetParam())),
+        : mParamLevel(std::get<PARAM_LEVEL>(GetParam())),
           mParamMute(std::get<PARAM_MUTE>(GetParam())) {
         std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
     }
@@ -67,7 +64,7 @@
     }
 
     Parameter::Specific getDefaultParamSpecific() {
-        Volume vol = Volume::make<Volume::levelDb>(Volume::MIN_LEVEL_DB);
+        Volume vol = Volume::make<Volume::levelDb>(-9600);
         Parameter::Specific specific = Parameter::Specific::make<Parameter::Specific::volume>(vol);
         return specific;
     }
@@ -87,6 +84,8 @@
             // validate parameter
             Descriptor desc;
             ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
+            // only set and get parameter if capability is valid
+            ASSERT_TRUE(isCapabilityValid(desc));
             const bool valid = isTagInRange(it.first, it.second, desc);
             const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
 
@@ -97,7 +96,7 @@
             expectParam.set<Parameter::specific>(specific);
             EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString();
 
-            // only get if parameter in range and set success
+            // only get if parameter is in range and set success
             if (expected == EX_NONE) {
                 Parameter getParam;
                 Parameter::Id id;
@@ -124,6 +123,11 @@
         mTags.push_back({Volume::mute, vol});
     }
 
+    bool isCapabilityValid(const Descriptor& desc) {
+        const Volume::Capability& volCap = desc.capability.get<Capability::volume>();
+        return (volCap.minLevelDb <= volCap.maxLevelDb);
+    }
+
     bool isTagInRange(const Volume::Tag& tag, const Volume& vol, const Descriptor& desc) const {
         const Volume::Capability& volCap = desc.capability.get<Capability::volume>();
         switch (tag) {
@@ -138,9 +142,21 @@
         }
     }
 
-    bool isLevelInRange(const Volume::Capability& cap, int level) const {
-        return level >= Volume::MIN_LEVEL_DB && level <= Volume::MAX_LEVEL_DB &&
-               level <= cap.maxLevel;
+    static std::vector<int> getLevelTestValues(
+            std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kFactoryDescList) {
+        int minLevelDb = std::numeric_limits<int>::max();
+        int maxLevelDb = std::numeric_limits<int>::min();
+        for (const auto& it : kFactoryDescList) {
+            maxLevelDb =
+                    std::max(it.second.capability.get<Capability::volume>().maxLevelDb, maxLevelDb);
+            minLevelDb = std::min(it.second.capability.get<Capability ::volume>().minLevelDb,
+                                  minLevelDb);
+        }
+        return {minLevelDb - 1, minLevelDb, -100, maxLevelDb, maxLevelDb + 1};
+    }
+
+    bool isLevelInRange(const Volume::Capability& volCap, int level) const {
+        return level >= volCap.minLevelDb && level <= volCap.maxLevelDb;
     }
 
   private:
@@ -160,12 +176,16 @@
 
 INSTANTIATE_TEST_SUITE_P(
         VolumeTest, VolumeParamTest,
-        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                                   IFactory::descriptor, kVolumeTypeUUID)),
-                           testing::ValuesIn(kLevelValues), testing::Bool()),
+        ::testing::Combine(
+                testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor,
+                                                                               kVolumeTypeUUID)),
+                testing::ValuesIn(VolumeParamTest::getLevelTestValues(
+                        EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor,
+                                                                     kVolumeTypeUUID))),
+                testing::Bool() /* mute */),
         [](const testing::TestParamInfo<VolumeParamTest::ParamType>& info) {
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
-            std::string level = std::to_string(std::get<PARAM_LEVEL_DB>(info.param));
+            std::string level = std::to_string(std::get<PARAM_LEVEL>(info.param));
             std::string mute = std::to_string(std::get<PARAM_MUTE>(info.param));
             std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
                                descriptor.common.name + "_UUID_" +