Effect AIDL: Refactor effect capability with Range implementation

Bug: 258124419
Test: atest --test-mapping hardware/interfaces/audio/aidl/vts:presubmit
Change-Id: I3e648348d43339bb7a9759887a3fbd65519088a4
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
index 038b7df..91c3dea 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
@@ -24,6 +24,7 @@
 #include <media/AidlConversionNdk.h>
 #include <media/AidlConversionEffect.h>
 #include <media/audiohal/AudioEffectUuid.h>
+#include <system/audio_effects/aidl_effects_utils.h>
 #include <system/audio_effects/effect_bassboost.h>
 
 #include <utils/Log.h>
@@ -37,6 +38,7 @@
 using ::aidl::android::aidl_utils::statusTFromBinderStatus;
 using ::aidl::android::hardware::audio::effect::BassBoost;
 using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Range;
 using ::android::status_t;
 using utils::EffectParamReader;
 using utils::EffectParamWriter;
@@ -89,10 +91,10 @@
             return param.writeToValue(&value);
         }
         case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
-            uint16_t value;
-            const auto& cap =
-                    VALUE_OR_RETURN_STATUS(aidl::android::UNION_GET(mDesc.capability, bassBoost));
-            value = VALUE_OR_RETURN_STATUS(convertIntegral<uint32_t>(cap.strengthSupported));
+            // an invalid range indicates not setting support for this parameter
+            uint16_t value =
+                    ::aidl::android::hardware::audio::effect::isRangeValid<Range::Tag::bassBoost>(
+                            BassBoost::strengthPm, mDesc.capability);
             return param.writeToValue(&value);
         }
         default: {
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
index 4ecaa07..4555c9f 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
@@ -147,8 +147,6 @@
                                                           DynamicsProcessing::inputGain);
             RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
 
-            DynamicsProcessing::Capability cap =
-                    mDesc.capability.get<Capability::dynamicsProcessing>();
             std::vector<DynamicsProcessing::InputGain> gains =
                     VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
                             aidlParam, DynamicsProcessing, dynamicsProcessing,
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
index 203a27b..4af5fd8 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
@@ -59,8 +59,34 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string DynamicsProcessingImpl::kEffectName = "DynamicsProcessing";
-const DynamicsProcessing::Capability DynamicsProcessingImpl::kCapability = {.minCutOffFreq = 220,
-                                                                            .maxCutOffFreq = 20000};
+
+const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMin =
+        DynamicsProcessing::EqBandConfig({.channel = 0,
+                                          .band = 0,
+                                          .enable = false,
+                                          .cutoffFrequencyHz = 220,
+                                          .gainDb = std::numeric_limits<float>::min()});
+const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMax =
+        DynamicsProcessing::EqBandConfig({.channel = std::numeric_limits<int>::max(),
+                                          .band = std::numeric_limits<int>::max(),
+                                          .enable = true,
+                                          .cutoffFrequencyHz = 20000,
+                                          .gainDb = std::numeric_limits<float>::max()});
+const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPreEqBandRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
+                {DynamicsProcessingImpl::kEqBandConfigMin}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
+                {DynamicsProcessingImpl::kEqBandConfigMax})};
+const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPostEqBandRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
+                {DynamicsProcessingImpl::kEqBandConfigMin}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
+                {DynamicsProcessingImpl::kEqBandConfigMax})};
+const Range DynamicsProcessingImpl::kRange =
+        Range::make<Range::dynamicsProcessing>({DynamicsProcessingImpl::kPreEqBandRange});
+
+const Capability DynamicsProcessingImpl::kCapability = {.range = {DynamicsProcessingImpl::kRange}};
+
 const Descriptor DynamicsProcessingImpl::kDescriptor = {
         .common = {.id = {.type = kDynamicsProcessingTypeUUID,
                           .uuid = kDynamicsProcessingImplUUID,
@@ -70,8 +96,7 @@
                              .volume = Flags::Volume::CTRL},
                    .name = DynamicsProcessingImpl::kEffectName,
                    .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::dynamicsProcessing>(
-                DynamicsProcessingImpl::kCapability)};
+        .capability = DynamicsProcessingImpl::kCapability};
 
 ndk::ScopedAStatus DynamicsProcessingImpl::open(const Parameter::Common& common,
                                                 const std::optional<Parameter::Specific>& specific,
@@ -138,6 +163,7 @@
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     auto& param = specific.get<Parameter::Specific::dynamicsProcessing>();
+    // TODO: check range here, dynamicsProcessing need customized method for nested parameters.
     auto tag = param.getTag();
 
     switch (tag) {
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
index 824ebea..26b6ead 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
@@ -28,7 +28,7 @@
   public:
     static const std::string kEffectName;
     static const Descriptor kDescriptor;
-    static const DynamicsProcessing::Capability kCapability;
+    static const Capability kCapability;
 
     DynamicsProcessingImpl() { LOG(DEBUG) << __func__; }
     ~DynamicsProcessingImpl() {
@@ -52,6 +52,11 @@
     std::string getEffectName() override { return kEffectName; }
 
   private:
+    static const DynamicsProcessing::EqBandConfig kEqBandConfigMin;
+    static const DynamicsProcessing::EqBandConfig kEqBandConfigMax;
+    static const Range::DynamicsProcessingRange kPreEqBandRange;
+    static const Range::DynamicsProcessingRange kPostEqBandRange;
+    static const Range kRange;
     std::shared_ptr<DynamicsProcessingContext> mContext;
     ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
                                                       Parameter::Specific* specific);
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
index 57a2be9..7978cc5 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
@@ -420,24 +420,18 @@
            validateStageEnablement(engine.postEqStage) && validateStageEnablement(engine.mbcStage);
 }
 
-inline bool DynamicsProcessingContext::validateCutoffFrequency(float freq) {
-    return freq >= DynamicsProcessingImpl::kCapability.minCutOffFreq &&
-            freq <= DynamicsProcessingImpl::kCapability.maxCutOffFreq;
-}
-
 bool DynamicsProcessingContext::validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band,
                                                      int maxChannel, int maxBand) {
-    return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand) &&
-           validateCutoffFrequency(band.cutoffFrequencyHz);
+    return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand);
 }
 
 bool DynamicsProcessingContext::validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band,
                                                       int maxChannel, int maxBand) {
     return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand) &&
-           validateCutoffFrequency(band.cutoffFrequencyHz) && validateTime(band.attackTimeMs) &&
-           validateTime(band.releaseTimeMs) && validateRatio(band.ratio) &&
-           validateBandDb(band.thresholdDb) && validateBandDb(band.kneeWidthDb) &&
-           validateBandDb(band.noiseGateThresholdDb) && validateRatio(band.expanderRatio);
+           validateTime(band.attackTimeMs) && validateTime(band.releaseTimeMs) &&
+           validateRatio(band.ratio) && validateBandDb(band.thresholdDb) &&
+           validateBandDb(band.kneeWidthDb) && validateBandDb(band.noiseGateThresholdDb) &&
+           validateRatio(band.expanderRatio);
 }
 
 bool DynamicsProcessingContext::validateLimiterConfig(
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
index e303efd..6124356 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -531,11 +531,6 @@
 }
 
 RetCode BundleContext::setBassBoostStrength(int strength) {
-    if (strength < 0 || strength > lvm::kBassBoostCap.maxStrengthPm) {
-        LOG(ERROR) << __func__ << " invalid strength: " << strength;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-
     // Update Control Parameter
     LVM_ControlParams_t params;
     {
@@ -555,10 +550,6 @@
 }
 
 RetCode BundleContext::setVolumeLevel(int level) {
-    if (level < lvm::kVolumeCap.minLevelDb || level > lvm::kVolumeCap.maxLevelDb) {
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-
     if (mMuteEnabled) {
         mLevelSaved = level / 100;
     } else {
@@ -584,10 +575,6 @@
 }
 
 RetCode BundleContext::setVirtualizerStrength(int strength) {
-    if (strength < 0 || strength > lvm::kVirtualizerCap.maxStrengthPm) {
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-
     // Update Control Parameter
     LVM_ControlParams_t params;
     {
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index 1996240..4652d8d 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -67,46 +67,53 @@
         {0, "Normal"},      {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
         {5, "Heavy Metal"}, {6, "Hip Hop"},   {7, "Jazz"},  {8, "Pop"},  {9, "Rock"}};
 
-static const Equalizer::Capability kEqCap = {.bandFrequencies = kEqBandFrequency,
-                                             .presets = kEqPresets};
 
+const std::vector<Range::EqualizerRange> kEqRanges = {
+        MAKE_RANGE(Equalizer, preset, 0, MAX_NUM_PRESETS - 1),
+        MAKE_RANGE(
+                Equalizer, bandLevels,
+                std::vector<Equalizer::BandLevel>{Equalizer::BandLevel(
+                        {.index = 0, .levelMb = std::numeric_limits<int>::min()})},
+                std::vector<Equalizer::BandLevel>{Equalizer::BandLevel(
+                        {.index = MAX_NUM_BANDS - 1, .levelMb = std::numeric_limits<int>::max()})}),
+        /* capability definition */
+        MAKE_RANGE(Equalizer, bandFrequencies, kEqBandFrequency, kEqBandFrequency),
+        MAKE_RANGE(Equalizer, presets, kEqPresets, kEqPresets),
+        /* get only parameters with range min > max */
+        MAKE_RANGE(Equalizer, centerFreqMh, std::vector<int>({1}), std::vector<int>({}))};
+static const Capability kEqCap = {.range = kEqRanges};
 static const std::string kEqualizerEffectName = "EqualizerBundle";
+static const Descriptor kEqualizerDesc = {.common = {.id = {.type = kEqualizerTypeUUID,
+                                                            .uuid = kEqualizerBundleImplUUID,
+                                                            .proxy = kEqualizerProxyUUID},
+                                                     .flags = {.type = Flags::Type::INSERT,
+                                                               .insert = Flags::Insert::FIRST,
+                                                               .volume = Flags::Volume::CTRL},
+                                                     .name = kEqualizerEffectName,
+                                                     .implementor = "NXP Software Ltd."},
+                                          .capability = kEqCap};
 
-static const Descriptor kEqualizerDesc = {
-        .common = {.id = {.type = kEqualizerTypeUUID,
-                          .uuid = kEqualizerBundleImplUUID,
-                          .proxy = kEqualizerProxyUUID},
-                   .flags = {.type = Flags::Type::INSERT,
-                             .insert = Flags::Insert::FIRST,
-                             .volume = Flags::Volume::CTRL},
-                   .name = kEqualizerEffectName,
-                   .implementor = "NXP Software Ltd."},
-        .capability = Capability::make<Capability::equalizer>(kEqCap)};
-
-static const bool mStrengthSupported = true;
-
-static const BassBoost::Capability kBassBoostCap = {.maxStrengthPm = 1000,
-                                                    .strengthSupported = mStrengthSupported};
-
+static const int mMaxStrengthSupported = 1000;
+static const std::vector<Range::BassBoostRange> kBassBoostRanges = {
+        MAKE_RANGE(BassBoost, strengthPm, 0, mMaxStrengthSupported)};
+static const Capability kBassBoostCap = {.range = kBassBoostRanges};
 static const std::string kBassBoostEffectName = "Dynamic Bass Boost";
+static const Descriptor kBassBoostDesc = {.common = {.id = {.type = kBassBoostTypeUUID,
+                                                            .uuid = kBassBoostBundleImplUUID,
+                                                            .proxy = kBassBoostProxyUUID},
+                                                     .flags = {.type = Flags::Type::INSERT,
+                                                               .insert = Flags::Insert::FIRST,
+                                                               .volume = Flags::Volume::CTRL,
+                                                               .deviceIndication = true},
+                                                     .cpuLoad = BASS_BOOST_CUP_LOAD_ARM9E,
+                                                     .memoryUsage = BUNDLE_MEM_USAGE,
+                                                     .name = kBassBoostEffectName,
+                                                     .implementor = "NXP Software Ltd."},
+                                          .capability = kBassBoostCap};
 
-static const Descriptor kBassBoostDesc = {
-        .common = {.id = {.type = kBassBoostTypeUUID,
-                          .uuid = kBassBoostBundleImplUUID,
-                          .proxy = kBassBoostProxyUUID},
-                   .flags = {.type = Flags::Type::INSERT,
-                             .insert = Flags::Insert::FIRST,
-                             .volume = Flags::Volume::CTRL,
-                             .deviceIndication = true},
-                   .cpuLoad = BASS_BOOST_CUP_LOAD_ARM9E,
-                   .memoryUsage = BUNDLE_MEM_USAGE,
-                   .name = kBassBoostEffectName,
-                   .implementor = "NXP Software Ltd."},
-        .capability = Capability::make<Capability::bassBoost>(kBassBoostCap)};
-
-static const Virtualizer::Capability kVirtualizerCap = {.maxStrengthPm = 1000,
-                                                        .strengthSupported = mStrengthSupported};
-
+static const std::vector<Range::VirtualizerRange> kVirtualizerRanges = {
+        MAKE_RANGE(Virtualizer, strengthPm, 0, mMaxStrengthSupported)};
+static const Capability kVirtualizerCap = {.range = kVirtualizerRanges};
 static const std::string kVirtualizerEffectName = "Virtualizer";
 
 static const Descriptor kVirtualizerDesc = {
@@ -121,24 +128,23 @@
                    .memoryUsage = BUNDLE_MEM_USAGE,
                    .name = kVirtualizerEffectName,
                    .implementor = "NXP Software Ltd."},
-        .capability = Capability::make<Capability::virtualizer>(kVirtualizerCap)};
+        .capability = kVirtualizerCap};
 
-static const Volume::Capability kVolumeCap = {.minLevelDb = -9600, .maxLevelDb = 0};
-
+static const std::vector<Range::VolumeRange> kVolumeRanges = {
+        MAKE_RANGE(Volume, levelDb, -9600, 0)};
+static const Capability kVolumeCap = {.range = kVolumeRanges};
 static const std::string kVolumeEffectName = "Volume";
-
-static const Descriptor kVolumeDesc = {
-        .common = {.id = {.type = kVolumeTypeUUID,
-                          .uuid = kVolumeBundleImplUUID,
-                          .proxy = std::nullopt},
-                   .flags = {.type = Flags::Type::INSERT,
-                             .insert = Flags::Insert::LAST,
-                             .volume = Flags::Volume::CTRL},
-                   .cpuLoad = VOLUME_CUP_LOAD_ARM9E,
-                   .memoryUsage = BUNDLE_MEM_USAGE,
-                   .name = kVolumeEffectName,
-                   .implementor = "NXP Software Ltd."},
-        .capability = Capability::make<Capability::volume>(kVolumeCap)};
+static const Descriptor kVolumeDesc = {.common = {.id = {.type = kVolumeTypeUUID,
+                                                         .uuid = kVolumeBundleImplUUID,
+                                                         .proxy = std::nullopt},
+                                                  .flags = {.type = Flags::Type::INSERT,
+                                                            .insert = Flags::Insert::LAST,
+                                                            .volume = Flags::Volume::CTRL},
+                                                  .cpuLoad = VOLUME_CUP_LOAD_ARM9E,
+                                                  .memoryUsage = BUNDLE_MEM_USAGE,
+                                                  .name = kVolumeEffectName,
+                                                  .implementor = "NXP Software Ltd."},
+                                       .capability = kVolumeCap};
 
 /* The following tables have been computed using the actual levels measured by the output of
  * white noise or pink noise (IEC268-1) for the EQ and BassBoost Effects. These are estimates of
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
index fd9f3dc..dc52c16 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "BundleTypes.h"
 #define LOG_TAG "EffectBundleAidl"
 #include <Utils.h>
 #include <algorithm>
@@ -173,6 +174,7 @@
 
 ndk::ScopedAStatus EffectBundleAidl::setParameterEqualizer(const Parameter::Specific& specific) {
     auto& eq = specific.get<Parameter::Specific::equalizer>();
+    RETURN_IF(!inRange(eq, lvm::kEqRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto eqTag = eq.getTag();
     switch (eqTag) {
         case Equalizer::preset:
@@ -193,6 +195,7 @@
 
 ndk::ScopedAStatus EffectBundleAidl::setParameterBassBoost(const Parameter::Specific& specific) {
     auto& bb = specific.get<Parameter::Specific::bassBoost>();
+    RETURN_IF(!inRange(bb, lvm::kBassBoostRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto bbTag = bb.getTag();
     switch (bbTag) {
         case BassBoost::strengthPm: {
@@ -210,6 +213,7 @@
 
 ndk::ScopedAStatus EffectBundleAidl::setParameterVirtualizer(const Parameter::Specific& specific) {
     auto& vr = specific.get<Parameter::Specific::virtualizer>();
+    RETURN_IF(!inRange(vr, lvm::kVirtualizerRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto vrTag = vr.getTag();
     switch (vrTag) {
         case Virtualizer::strengthPm: {
@@ -235,6 +239,7 @@
 
 ndk::ScopedAStatus EffectBundleAidl::setParameterVolume(const Parameter::Specific& specific) {
     auto& vol = specific.get<Parameter::Specific::volume>();
+    RETURN_IF(!inRange(vol, lvm::kVolumeRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto volTag = vol.getTag();
     switch (volTag) {
         case Volume::levelDb: {
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
index 51825ca..018f3bc 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "ReverbTypes.h"
 #define LOG_TAG "EffectReverb"
 #include <Utils.h>
 #include <algorithm>
@@ -132,6 +133,7 @@
 
 ndk::ScopedAStatus EffectReverb::setParameterPresetReverb(const Parameter::Specific& specific) {
     auto& prParam = specific.get<Parameter::Specific::presetReverb>();
+    RETURN_IF(!inRange(prParam, lvm::kPresetReverbRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto tag = prParam.getTag();
 
     switch (tag) {
@@ -152,6 +154,7 @@
 ndk::ScopedAStatus EffectReverb::setParameterEnvironmentalReverb(
         const Parameter::Specific& specific) {
     auto& erParam = specific.get<Parameter::Specific::environmentalReverb>();
+    RETURN_IF(!inRange(erParam, lvm::kEnvReverbRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto tag = erParam.getTag();
 
     switch (tag) {
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp
index d35c22b..87aa12b 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp
@@ -139,12 +139,6 @@
 }
 
 RetCode ReverbContext::setEnvironmentalReverbRoomLevel(int roomLevel) {
-    if (roomLevel < lvm::kEnvReverbCap.minRoomLevelMb ||
-        roomLevel > lvm::kEnvReverbCap.maxRoomLevelMb) {
-        LOG(ERROR) << __func__ << " invalid roomLevel: " << roomLevel;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-
     // Update Control Parameter
     LVREV_ControlParams_st params;
     {
@@ -165,12 +159,6 @@
 }
 
 RetCode ReverbContext::setEnvironmentalReverbRoomHfLevel(int roomHfLevel) {
-    if (roomHfLevel < lvm::kEnvReverbCap.minRoomHfLevelMb ||
-        roomHfLevel > lvm::kEnvReverbCap.maxRoomHfLevelMb) {
-        LOG(ERROR) << __func__ << " invalid roomHfLevel: " << roomHfLevel;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-
     // Update Control Parameter
     LVREV_ControlParams_st params;
     {
@@ -188,10 +176,6 @@
 }
 
 RetCode ReverbContext::setEnvironmentalReverbDecayTime(int decayTime) {
-    if (decayTime < 0 || decayTime > lvm::kEnvReverbCap.maxDecayTimeMs) {
-        LOG(ERROR) << __func__ << " invalid decayTime: " << decayTime;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
     int time = decayTime;
     if (time > lvm::kMaxT60) {
         time = lvm::kMaxT60;
@@ -215,12 +199,6 @@
 }
 
 RetCode ReverbContext::setEnvironmentalReverbDecayHfRatio(int decayHfRatio) {
-    if (decayHfRatio < lvm::kEnvReverbCap.minDecayHfRatioPm ||
-        decayHfRatio > lvm::kEnvReverbCap.maxDecayHfRatioPm) {
-        LOG(ERROR) << __func__ << " invalid decayHfRatio: " << decayHfRatio;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-
     // Update Control Parameter
     LVREV_ControlParams_st params;
     {
@@ -238,11 +216,6 @@
 }
 
 RetCode ReverbContext::setEnvironmentalReverbLevel(int level) {
-    if (level < lvm::kEnvReverbCap.minLevelMb || level > lvm::kEnvReverbCap.maxLevelMb) {
-        LOG(ERROR) << __func__ << " invalid level: " << level;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-
     // Update Control Parameter
     LVREV_ControlParams_st params;
     {
@@ -263,20 +236,11 @@
 }
 
 RetCode ReverbContext::setEnvironmentalReverbDelay(int delay) {
-    if (delay < 0 || delay > lvm::kEnvReverbCap.maxDelayMs) {
-        LOG(ERROR) << __func__ << " invalid delay: " << delay;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
     mDelay = delay;
     return RetCode::SUCCESS;
 }
 
 RetCode ReverbContext::setEnvironmentalReverbDiffusion(int diffusion) {
-    if (diffusion < 0 || diffusion > lvm::kEnvReverbCap.maxDiffusionPm) {
-        LOG(ERROR) << __func__ << " invalid diffusion: " << diffusion;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-
     // Update Control Parameter
     LVREV_ControlParams_st params;
     {
@@ -294,11 +258,6 @@
 }
 
 RetCode ReverbContext::setEnvironmentalReverbDensity(int density) {
-    if (density < 0 || density > lvm::kEnvReverbCap.maxDensityPm) {
-        LOG(ERROR) << __func__ << " invalid density: " << density;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-
     // Update Control Parameter
     LVREV_ControlParams_st params;
     {
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h
index e37602c..8dcda87 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h
@@ -21,6 +21,7 @@
 #include <audio_effects/effect_environmentalreverb.h>
 #include <audio_effects/effect_presetreverb.h>
 #include "effect-impl/EffectUUID.h"
+#include "effect-impl/EffectTypes.h"
 // from Reverb/lib
 #include "LVREV.h"
 
@@ -35,51 +36,51 @@
 constexpr inline int kCpuLoadARM9E = 470;                      // Expressed in 0.1 MIPS
 constexpr inline int kMemUsage = (71 + (kMaxFrameSize >> 7));  // Expressed in kB
 
-static const EnvironmentalReverb::Capability kEnvReverbCap = {.minRoomLevelMb = lvm::kMinLevel,
-                                                              .maxRoomLevelMb = 0,
-                                                              .minRoomHfLevelMb = -4000,
-                                                              .maxRoomHfLevelMb = 0,
-                                                              .maxDecayTimeMs = lvm::kMaxT60,
-                                                              .minDecayHfRatioPm = 100,
-                                                              .maxDecayHfRatioPm = 2000,
-                                                              .minLevelMb = lvm::kMinLevel,
-                                                              .maxLevelMb = 0,
-                                                              .maxDelayMs = 65,
-                                                              .maxDiffusionPm = 1000,
-                                                              .maxDensityPm = 1000};
+static const std::vector<Range::EnvironmentalReverbRange> kEnvReverbRanges = {
+        MAKE_RANGE(EnvironmentalReverb, roomLevelMb, lvm::kMinLevel, 0),
+        MAKE_RANGE(EnvironmentalReverb, roomHfLevelMb, -4000, 0),
+        MAKE_RANGE(EnvironmentalReverb, decayTimeMs, 0, lvm::kMaxT60),
+        MAKE_RANGE(EnvironmentalReverb, decayHfRatioPm, 100, 2000),
+        MAKE_RANGE(EnvironmentalReverb, levelMb, lvm::kMinLevel, 0),
+        MAKE_RANGE(EnvironmentalReverb, delayMs, 0, 65),
+        MAKE_RANGE(EnvironmentalReverb, diffusionPm, 0, 1000),
+        MAKE_RANGE(EnvironmentalReverb, densityPm, 0, 1000)};
+static const Capability kEnvReverbCap = {
+        .range = Range::make<Range::environmentalReverb>(kEnvReverbRanges)};
 
 // NXP SW auxiliary environmental reverb
 static const std::string kAuxEnvReverbEffectName = "Auxiliary Environmental Reverb";
-static const Descriptor kAuxEnvReverbDesc = {
-        .common = {.id = {.type = kEnvReverbTypeUUID,
-                          .uuid = kAuxEnvReverbImplUUID,
-                          .proxy = std::nullopt},
-                   .flags = {.type = Flags::Type::AUXILIARY},
-                   .cpuLoad = kCpuLoadARM9E,
-                   .memoryUsage = kMemUsage,
-                   .name = kAuxEnvReverbEffectName,
-                   .implementor = "NXP Software Ltd."},
-        .capability = Capability::make<Capability::environmentalReverb>(kEnvReverbCap)};
+static const Descriptor kAuxEnvReverbDesc = {.common = {.id = {.type = kEnvReverbTypeUUID,
+                                                               .uuid = kAuxEnvReverbImplUUID,
+                                                               .proxy = std::nullopt},
+                                                        .flags = {.type = Flags::Type::AUXILIARY},
+                                                        .cpuLoad = kCpuLoadARM9E,
+                                                        .memoryUsage = kMemUsage,
+                                                        .name = kAuxEnvReverbEffectName,
+                                                        .implementor = "NXP Software Ltd."},
+                                             .capability = kEnvReverbCap};
 
 // NXP SW insert environmental reverb
 static const std::string kInsertEnvReverbEffectName = "Insert Environmental Reverb";
-static const Descriptor kInsertEnvReverbDesc = {
-        .common = {.id = {.type = kEnvReverbTypeUUID,
-                          .uuid = kInsertEnvReverbImplUUID,
-                          .proxy = std::nullopt},
-                   .flags = {.type = Flags::Type::INSERT,
-                             .insert = Flags::Insert::FIRST,
-                             .volume = Flags::Volume::CTRL},
-                   .cpuLoad = kCpuLoadARM9E,
-                   .memoryUsage = kMemUsage,
-                   .name = kInsertEnvReverbEffectName,
-                   .implementor = "NXP Software Ltd."},
-        .capability = Capability::make<Capability::environmentalReverb>(kEnvReverbCap)};
+static const Descriptor kInsertEnvReverbDesc = {.common = {.id = {.type = kEnvReverbTypeUUID,
+                                                                  .uuid = kInsertEnvReverbImplUUID,
+                                                                  .proxy = std::nullopt},
+                                                           .flags = {.type = Flags::Type::INSERT,
+                                                                     .insert = Flags::Insert::FIRST,
+                                                                     .volume = Flags::Volume::CTRL},
+                                                           .cpuLoad = kCpuLoadARM9E,
+                                                           .memoryUsage = kMemUsage,
+                                                           .name = kInsertEnvReverbEffectName,
+                                                           .implementor = "NXP Software Ltd."},
+                                                .capability = kEnvReverbCap};
 
 static const std::vector<PresetReverb::Presets> kSupportedPresets{
         ndk::enum_range<PresetReverb::Presets>().begin(),
         ndk::enum_range<PresetReverb::Presets>().end()};
-static const PresetReverb::Capability kPresetReverbCap = {.supportedPresets = kSupportedPresets};
+static const std::vector<Range::PresetReverbRange> kPresetReverbRanges = {
+        MAKE_RANGE(PresetReverb, supportedPresets, kSupportedPresets, kSupportedPresets)};
+static const Capability kPresetReverbCap = {
+        .range = Range::make<Range::presetReverb>(kPresetReverbRanges)};
 
 // NXP SW auxiliary preset reverb
 static const std::string kAuxPresetReverbEffectName = "Auxiliary Preset Reverb";
@@ -92,7 +93,7 @@
                    .memoryUsage = kMemUsage,
                    .name = kAuxPresetReverbEffectName,
                    .implementor = "NXP Software Ltd."},
-        .capability = Capability::make<Capability::presetReverb>(kPresetReverbCap)};
+        .capability = kPresetReverbCap};
 
 // NXP SW insert preset reverb
 static const std::string kInsertPresetReverbEffectName = "Insert Preset Reverb";
@@ -107,7 +108,7 @@
                    .memoryUsage = kMemUsage,
                    .name = kInsertPresetReverbEffectName,
                    .implementor = "NXP Software Ltd."},
-        .capability = Capability::make<Capability::presetReverb>(kPresetReverbCap)};
+        .capability = kPresetReverbCap};
 
 enum class ReverbEffectType {
     AUX_ENV,
diff --git a/media/libeffects/visualizer/aidl/Visualizer.cpp b/media/libeffects/visualizer/aidl/Visualizer.cpp
index 28a7287..6e7833c 100644
--- a/media/libeffects/visualizer/aidl/Visualizer.cpp
+++ b/media/libeffects/visualizer/aidl/Visualizer.cpp
@@ -54,9 +54,16 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string VisualizerImpl::kEffectName = "Visualizer";
-const Visualizer::Capability VisualizerImpl::kCapability = {
-        .maxLatencyMs = VisualizerContext::kMaxLatencyMs,
-        .captureSampleRange = {.min = 0, .max = VisualizerContext::kMaxCaptureBufSize}};
+const std::vector<Range::VisualizerRange> VisualizerImpl::kRanges = {
+        MAKE_RANGE(Visualizer, latencyMs, 0, VisualizerContext::kMaxLatencyMs),
+        MAKE_RANGE(Visualizer, captureSamples, 0, VisualizerContext::kMaxCaptureBufSize),
+        /* get only parameters, set invalid range (min > max) to indicate not support set */
+        MAKE_RANGE(Visualizer, measurement, Visualizer::Measurement({.peak = 1, .rms = 1}),
+                   Visualizer::Measurement({.peak = 0, .rms = 0})),
+        MAKE_RANGE(Visualizer, captureSampleBuffer, std::vector<uint8_t>({1}),
+                   std::vector<uint8_t>({0}))};
+const Capability VisualizerImpl::kCapability = {
+        .range = Range::make<Range::visualizer>(VisualizerImpl::kRanges)};
 const Descriptor VisualizerImpl::kDescriptor = {
         .common = {.id = {.type = kVisualizerTypeUUID,
                           .uuid = kVisualizerImplUUID,
@@ -66,7 +73,7 @@
                              .volume = Flags::Volume::CTRL},
                    .name = VisualizerImpl::kEffectName,
                    .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::visualizer>(VisualizerImpl::kCapability)};
+        .capability = VisualizerImpl::kCapability};
 
 ndk::ScopedAStatus VisualizerImpl::getDescriptor(Descriptor* _aidl_return) {
     RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
@@ -96,32 +103,13 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus VisualizerImpl::setOnlyParameter(
-        const Visualizer::SetOnlyParameters& param) {
-    auto tag = param.getTag();
-    switch (tag) {
-        case Visualizer::SetOnlyParameters::latencyMs: {
-            RETURN_IF(mContext->setDownstreamLatency(
-                              param.get<Visualizer::SetOnlyParameters::latencyMs>()) !=
-                              RetCode::SUCCESS,
-                      EX_ILLEGAL_ARGUMENT, "setLatencyFailed");
-            break;
-        }
-        default: {
-            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
-                    EX_ILLEGAL_ARGUMENT, "setOnlyParameterTagNotSupported");
-        }
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
 ndk::ScopedAStatus VisualizerImpl::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     auto& param = specific.get<Parameter::Specific::visualizer>();
+    RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     const auto tag = param.getTag();
     switch (tag) {
         case Visualizer::captureSamples: {
@@ -142,8 +130,11 @@
                       EX_ILLEGAL_ARGUMENT, "setMeasurementModeFailed");
             return ndk::ScopedAStatus::ok();
         }
-        case Visualizer::setOnlyParameters: {
-            return setOnlyParameter(param.get<Visualizer::setOnlyParameters>());
+        case Visualizer::latencyMs: {
+            RETURN_IF(mContext->setDownstreamLatency(param.get<Visualizer::latencyMs>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setLatencyFailed");
+            return ndk::ScopedAStatus::ok();
         }
         default: {
             LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
@@ -153,30 +144,6 @@
     }
 }
 
-ndk::ScopedAStatus VisualizerImpl::getOnlyParameter(const Visualizer::GetOnlyParameters::Tag tag,
-                                                    Parameter::Specific* specific) {
-    Visualizer visualizer;
-    Visualizer::GetOnlyParameters param;
-    switch (tag) {
-        case Visualizer::GetOnlyParameters::measurement: {
-            param.set<Visualizer::GetOnlyParameters::measurement>(mContext->getMeasure());
-            break;
-        }
-        case Visualizer::GetOnlyParameters::captureSampleBuffer: {
-            param.set<Visualizer::GetOnlyParameters::captureSampleBuffer>(mContext->capture());
-            break;
-        }
-        default: {
-            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
-                    EX_ILLEGAL_ARGUMENT, "setOnlyParameterTagNotSupported");
-        }
-    }
-    visualizer.set<Visualizer::getOnlyParameters>(param);
-    specific->set<Parameter::Specific::visualizer>(visualizer);
-    return ndk::ScopedAStatus::ok();
-}
-
 ndk::ScopedAStatus VisualizerImpl::getParameterSpecific(const Parameter::Id& id,
                                                         Parameter::Specific* specific) {
     RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
@@ -188,9 +155,6 @@
         case Visualizer::Id::commonTag: {
             return getParameterVisualizer(specificId.get<Visualizer::Id::commonTag>(), specific);
         }
-        case Visualizer::Id::getOnlyParamTag: {
-            return getOnlyParameter(specificId.get<Visualizer::Id::getOnlyParamTag>(), specific);
-        }
         default: {
             LOG(ERROR) << __func__ << " unsupported tag: " << toString(specificTag);
             return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
@@ -218,6 +182,18 @@
             param.set<Visualizer::measurementMode>(mContext->getMeasurementMode());
             break;
         }
+        case Visualizer::measurement: {
+            param.set<Visualizer::measurement>(mContext->getMeasure());
+            break;
+        }
+        case Visualizer::captureSampleBuffer: {
+            param.set<Visualizer::captureSampleBuffer>(mContext->capture());
+            break;
+        }
+        case Visualizer::latencyMs: {
+            param.set<Visualizer::latencyMs>(mContext->getDownstreamLatency());
+            break;
+        }
         default: {
             LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
             return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
diff --git a/media/libeffects/visualizer/aidl/Visualizer.h b/media/libeffects/visualizer/aidl/Visualizer.h
index 5908d9a..f6e1d6d 100644
--- a/media/libeffects/visualizer/aidl/Visualizer.h
+++ b/media/libeffects/visualizer/aidl/Visualizer.h
@@ -28,7 +28,7 @@
 class VisualizerImpl final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const Visualizer::Capability kCapability;
+    static const Capability kCapability;
     static const Descriptor kDescriptor;
     VisualizerImpl() { LOG(DEBUG) << __func__; }
     ~VisualizerImpl() {
@@ -49,12 +49,10 @@
     std::string getEffectName() override { return kEffectName; }
 
   private:
+    static const std::vector<Range::VisualizerRange> kRanges;
     std::shared_ptr<VisualizerContext> mContext;
     ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
                                                     Parameter::Specific* specific);
-    ndk::ScopedAStatus setOnlyParameter(const Visualizer::SetOnlyParameters& param);
-    ndk::ScopedAStatus getOnlyParameter(const Visualizer::GetOnlyParameters::Tag tag,
-                                        Parameter::Specific* specific);
 };
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.cpp b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
index 1965e0e..4405407 100644
--- a/media/libeffects/visualizer/aidl/VisualizerContext.cpp
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
@@ -88,11 +88,6 @@
 
 RetCode VisualizerContext::setCaptureSamples(int samples) {
     std::lock_guard lg(mMutex);
-    if (samples < 0 || (unsigned)samples > kMaxCaptureBufSize) {
-        LOG(ERROR) << __func__ << " captureSamples " << samples << " exceed valid range: 0 - "
-                   << kMaxCaptureBufSize;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
     mCaptureSamples = samples;
     return RetCode::SUCCESS;
 }
@@ -122,16 +117,16 @@
 }
 
 RetCode VisualizerContext::setDownstreamLatency(int latency) {
-    if (latency < 0 || (unsigned)latency > kMaxLatencyMs) {
-        LOG(ERROR) << __func__ << " latency " << latency << " exceed valid range: 0 - "
-                   << kMaxLatencyMs;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
     std::lock_guard lg(mMutex);
     mDownstreamLatency = latency;
     return RetCode::SUCCESS;
 }
 
+int VisualizerContext::getDownstreamLatency() {
+    std::lock_guard lg(mMutex);
+    return mDownstreamLatency;
+}
+
 uint32_t VisualizerContext::getDeltaTimeMsFromUpdatedTime_l() {
     uint32_t deltaMs = 0;
     if (mBufferUpdateTime.tv_sec != 0) {
@@ -149,7 +144,7 @@
     return deltaMs;
 }
 
-Visualizer::GetOnlyParameters::Measurement VisualizerContext::getMeasure() {
+Visualizer::Measurement VisualizerContext::getMeasure() {
     uint16_t peakU16 = 0;
     float sumRmsSquared = 0.0f;
     uint8_t nbValidMeasurements = 0;
@@ -184,7 +179,7 @@
     }
 
     float rms = nbValidMeasurements == 0 ? 0.0f : sqrtf(sumRmsSquared / nbValidMeasurements);
-    Visualizer::GetOnlyParameters::Measurement measure;
+    Visualizer::Measurement measure;
     // convert from I16 sample values to mB and write results
     measure.rms = (rms < 0.000016f) ? -9600 : (int32_t)(2000 * log10(rms / 32767.0f));
     measure.peak = (peakU16 == 0) ? -9600 : (int32_t)(2000 * log10(peakU16 / 32767.0f));
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.h b/media/libeffects/visualizer/aidl/VisualizerContext.h
index bfda0b9..3cb711e 100644
--- a/media/libeffects/visualizer/aidl/VisualizerContext.h
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.h
@@ -45,10 +45,11 @@
     RetCode setScalingMode(Visualizer::ScalingMode mode);
     Visualizer::ScalingMode getScalingMode();
     RetCode setDownstreamLatency(int latency);
+    int getDownstreamLatency();
 
     IEffect::Status process(float* in, float* out, int samples);
     // Gets the current measurements, measured by process() and consumed by getParameter()
-    Visualizer::GetOnlyParameters::Measurement getMeasure();
+    Visualizer::Measurement getMeasure();
     // Gets the latest PCM capture, data captured by process() and consumed by getParameter()
     std::vector<uint8_t> capture();