Effect AIDL: Refactor effect capability with Range implementation

Bug: 258124419
Test: atest --test-mapping hardware/interfaces/audio/aidl/vts:presubmit
Change-Id: Ie76270e91471a30f7dda1883c510cd318745855f
diff --git a/audio/aidl/default/EffectImpl.cpp b/audio/aidl/default/EffectImpl.cpp
index 403a4b9..fa9eb95 100644
--- a/audio/aidl/default/EffectImpl.cpp
+++ b/audio/aidl/default/EffectImpl.cpp
@@ -78,7 +78,7 @@
 ndk::ScopedAStatus EffectImpl::setParameter(const Parameter& param) {
     LOG(DEBUG) << __func__ << " with: " << param.toString();
 
-    auto tag = param.getTag();
+    const auto tag = param.getTag();
     switch (tag) {
         case Parameter::common:
         case Parameter::deviceDescription:
diff --git a/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp
index 40b46e0..f5af81e 100644
--- a/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp
+++ b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp
@@ -30,6 +30,7 @@
 using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::kAcousticEchoCancelerSwImplUUID;
+using aidl::android::hardware::audio::effect::Range;
 using aidl::android::media::audio::common::AudioUuid;
 
 extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
@@ -60,8 +61,14 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string AcousticEchoCancelerSw::kEffectName = "AcousticEchoCancelerSw";
-const AcousticEchoCanceler::Capability AcousticEchoCancelerSw::kCapability = {
-        .maxEchoDelayUs = 500, .supportMobileMode = false};
+
+const std::vector<Range::AcousticEchoCancelerRange> AcousticEchoCancelerSw::kRanges = {
+        MAKE_RANGE(AcousticEchoCanceler, echoDelayUs, 0, 500),
+        /* mobile mode not supported, and not settable */
+        MAKE_RANGE(AcousticEchoCanceler, mobileMode, false, false)};
+
+const Capability AcousticEchoCancelerSw::kCapability = {.range = AcousticEchoCancelerSw::kRanges};
+
 const Descriptor AcousticEchoCancelerSw::kDescriptor = {
         .common = {.id = {.type = kAcousticEchoCancelerTypeUUID,
                           .uuid = kAcousticEchoCancelerSwImplUUID,
@@ -71,8 +78,7 @@
                              .volume = Flags::Volume::CTRL},
                    .name = AcousticEchoCancelerSw::kEffectName,
                    .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::acousticEchoCanceler>(
-                AcousticEchoCancelerSw::kCapability)};
+        .capability = AcousticEchoCancelerSw::kCapability};
 
 ndk::ScopedAStatus AcousticEchoCancelerSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
@@ -87,8 +93,9 @@
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     auto& param = specific.get<Parameter::Specific::acousticEchoCanceler>();
-    auto tag = param.getTag();
+    RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
 
+    auto tag = param.getTag();
     switch (tag) {
         case AcousticEchoCanceler::echoDelayUs: {
             RETURN_IF(mContext->setEchoDelay(param.get<AcousticEchoCanceler::echoDelayUs>()) !=
@@ -182,10 +189,6 @@
 }
 
 RetCode AcousticEchoCancelerSwContext::setEchoDelay(int echoDelayUs) {
-    if (echoDelayUs < 0 || echoDelayUs > AcousticEchoCancelerSw::kCapability.maxEchoDelayUs) {
-        LOG(DEBUG) << __func__ << " illegal delay " << echoDelayUs;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
     mEchoDelayUs = echoDelayUs;
     return RetCode::SUCCESS;
 }
diff --git a/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.h b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.h
index 5f1bc46..753207d 100644
--- a/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.h
+++ b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <aidl/android/hardware/audio/effect/Range.h>
 #include <fmq/AidlMessageQueue.h>
 #include <cstdlib>
 #include <memory>
@@ -43,8 +44,7 @@
 class AcousticEchoCancelerSw final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const bool kStrengthSupported;
-    static const AcousticEchoCanceler::Capability kCapability;
+    static const Capability kCapability;
     static const Descriptor kDescriptor;
     AcousticEchoCancelerSw() { LOG(DEBUG) << __func__; }
     ~AcousticEchoCancelerSw() {
@@ -65,6 +65,7 @@
     IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
 
   private:
+    static const std::vector<Range::AcousticEchoCancelerRange> kRanges;
     std::shared_ptr<AcousticEchoCancelerSwContext> mContext;
     ndk::ScopedAStatus getParameterAcousticEchoCanceler(const AcousticEchoCanceler::Tag& tag,
                                                         Parameter::Specific* specific);
diff --git a/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.cpp b/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.cpp
index 8c706ef..30d7910 100644
--- a/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.cpp
+++ b/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.cpp
@@ -60,8 +60,13 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string AutomaticGainControlSw::kEffectName = "AutomaticGainControlSw";
-const AutomaticGainControl::Capability AutomaticGainControlSw::kCapability = {
-        .maxFixedDigitalGainMb = 50000, .maxSaturationMarginMb = 10000};
+
+const std::vector<Range::AutomaticGainControlRange> AutomaticGainControlSw::kRanges = {
+        MAKE_RANGE(AutomaticGainControl, fixedDigitalGainMb, 0, 50000),
+        MAKE_RANGE(AutomaticGainControl, saturationMarginMb, 0, 10000)};
+
+const Capability AutomaticGainControlSw::kCapability = {.range = AutomaticGainControlSw::kRanges};
+
 const Descriptor AutomaticGainControlSw::kDescriptor = {
         .common = {.id = {.type = kAutomaticGainControlTypeUUID,
                           .uuid = kAutomaticGainControlSwImplUUID,
@@ -71,8 +76,7 @@
                              .volume = Flags::Volume::CTRL},
                    .name = AutomaticGainControlSw::kEffectName,
                    .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::automaticGainControl>(
-                AutomaticGainControlSw::kCapability)};
+        .capability = AutomaticGainControlSw::kCapability};
 
 ndk::ScopedAStatus AutomaticGainControlSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
@@ -87,8 +91,8 @@
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     auto& param = specific.get<Parameter::Specific::automaticGainControl>();
+    RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto tag = param.getTag();
-
     switch (tag) {
         case AutomaticGainControl::fixedDigitalGainMb: {
             RETURN_IF(mContext->setDigitalGain(
@@ -196,10 +200,6 @@
 }
 
 RetCode AutomaticGainControlSwContext::setDigitalGain(int gain) {
-    if (gain < 0 || gain > AutomaticGainControlSw::kCapability.maxFixedDigitalGainMb) {
-        LOG(DEBUG) << __func__ << " illegal digital gain " << gain;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
     mDigitalGain = gain;
     return RetCode::SUCCESS;
 }
@@ -219,10 +219,6 @@
 }
 
 RetCode AutomaticGainControlSwContext::setSaturationMargin(int margin) {
-    if (margin < 0 || margin > AutomaticGainControlSw::kCapability.maxSaturationMarginMb) {
-        LOG(DEBUG) << __func__ << " illegal saturationMargin " << margin;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
     mSaturationMargin = margin;
     return RetCode::SUCCESS;
 }
diff --git a/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.h b/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.h
index 2724835..9327410 100644
--- a/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.h
+++ b/audio/aidl/default/automaticGainControl/AutomaticGainControlSw.h
@@ -51,7 +51,7 @@
   public:
     static const std::string kEffectName;
     static const bool kStrengthSupported;
-    static const AutomaticGainControl::Capability kCapability;
+    static const Capability kCapability;
     static const Descriptor kDescriptor;
     AutomaticGainControlSw() { LOG(DEBUG) << __func__; }
     ~AutomaticGainControlSw() {
@@ -72,6 +72,7 @@
     IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
 
   private:
+    static const std::vector<Range::AutomaticGainControlRange> kRanges;
     std::shared_ptr<AutomaticGainControlSwContext> mContext;
     ndk::ScopedAStatus getParameterAutomaticGainControl(const AutomaticGainControl::Tag& tag,
                                                         Parameter::Specific* specific);
diff --git a/audio/aidl/default/bassboost/BassBoostSw.cpp b/audio/aidl/default/bassboost/BassBoostSw.cpp
index 0c7ebe1..e50f0a2 100644
--- a/audio/aidl/default/bassboost/BassBoostSw.cpp
+++ b/audio/aidl/default/bassboost/BassBoostSw.cpp
@@ -61,9 +61,10 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string BassBoostSw::kEffectName = "BassBoostSw";
-const bool BassBoostSw::kStrengthSupported = true;
-const BassBoost::Capability BassBoostSw::kCapability = {.maxStrengthPm = 1000,
-                                                        .strengthSupported = kStrengthSupported};
+
+const std::vector<Range::BassBoostRange> BassBoostSw::kRanges = {
+        MAKE_RANGE(BassBoost, strengthPm, 0, 1000)};
+const Capability BassBoostSw::kCapability = {.range = {BassBoostSw::kRanges}};
 const Descriptor BassBoostSw::kDescriptor = {
         .common = {.id = {.type = kBassBoostTypeUUID,
                           .uuid = kBassBoostSwImplUUID,
@@ -73,7 +74,7 @@
                              .volume = Flags::Volume::CTRL},
                    .name = BassBoostSw::kEffectName,
                    .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::bassBoost>(BassBoostSw::kCapability)};
+        .capability = BassBoostSw::kCapability};
 
 ndk::ScopedAStatus BassBoostSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
@@ -87,15 +88,14 @@
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     auto& bbParam = specific.get<Parameter::Specific::bassBoost>();
+    RETURN_IF(!inRange(bbParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto tag = bbParam.getTag();
 
     switch (tag) {
         case BassBoost::strengthPm: {
-            RETURN_IF(!kStrengthSupported, EX_ILLEGAL_ARGUMENT, "SettingStrengthNotSupported");
-
-            RETURN_IF(mContext->setBbStrengthPm(bbParam.get<BassBoost::strengthPm>()) !=
-                              RetCode::SUCCESS,
-                      EX_ILLEGAL_ARGUMENT, "strengthPmNotSupported");
+            const auto strength = bbParam.get<BassBoost::strengthPm>();
+            RETURN_IF(mContext->setBbStrengthPm(strength) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT,
+                      "strengthPmNotSupported");
             return ndk::ScopedAStatus::ok();
         }
         default: {
@@ -173,11 +173,6 @@
 }
 
 RetCode BassBoostSwContext::setBbStrengthPm(int strength) {
-    if (strength < 0 || strength > BassBoostSw::kCapability.maxStrengthPm) {
-        LOG(ERROR) << __func__ << " invalid strength: " << strength;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-    // TODO : Add implementation to apply new strength
     mStrength = strength;
     return RetCode::SUCCESS;
 }
diff --git a/audio/aidl/default/bassboost/BassBoostSw.h b/audio/aidl/default/bassboost/BassBoostSw.h
index 65c01c8..8d183dd 100644
--- a/audio/aidl/default/bassboost/BassBoostSw.h
+++ b/audio/aidl/default/bassboost/BassBoostSw.h
@@ -43,8 +43,7 @@
 class BassBoostSw final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const bool kStrengthSupported;
-    static const BassBoost::Capability kCapability;
+    static const Capability kCapability;
     static const Descriptor kDescriptor;
     BassBoostSw() { LOG(DEBUG) << __func__; }
     ~BassBoostSw() {
@@ -65,6 +64,7 @@
     IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
 
   private:
+    static const std::vector<Range::BassBoostRange> kRanges;
     std::shared_ptr<BassBoostSwContext> mContext;
     ndk::ScopedAStatus getParameterBassBoost(const BassBoost::Tag& tag,
                                              Parameter::Specific* specific);
diff --git a/audio/aidl/default/downmix/DownmixSw.cpp b/audio/aidl/default/downmix/DownmixSw.cpp
index 7bb958d..0af95d0 100644
--- a/audio/aidl/default/downmix/DownmixSw.cpp
+++ b/audio/aidl/default/downmix/DownmixSw.cpp
@@ -60,17 +60,14 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string DownmixSw::kEffectName = "DownmixSw";
-const Downmix::Capability DownmixSw::kCapability;
 const Descriptor DownmixSw::kDescriptor = {
-        .common = {.id = {.type = kDownmixTypeUUID,
-                          .uuid = kDownmixSwImplUUID,
-                          .proxy = std::nullopt},
-                   .flags = {.type = Flags::Type::INSERT,
-                             .insert = Flags::Insert::FIRST,
-                             .volume = Flags::Volume::CTRL},
-                   .name = kEffectName,
-                   .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::downmix>(kCapability)};
+        .common = {
+                .id = {.type = kDownmixTypeUUID, .uuid = kDownmixSwImplUUID, .proxy = std::nullopt},
+                .flags = {.type = Flags::Type::INSERT,
+                          .insert = Flags::Insert::FIRST,
+                          .volume = Flags::Volume::CTRL},
+                .name = kEffectName,
+                .implementor = "The Android Open Source Project"}};
 
 ndk::ScopedAStatus DownmixSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
diff --git a/audio/aidl/default/downmix/DownmixSw.h b/audio/aidl/default/downmix/DownmixSw.h
index 51546c1..37c978b 100644
--- a/audio/aidl/default/downmix/DownmixSw.h
+++ b/audio/aidl/default/downmix/DownmixSw.h
@@ -47,7 +47,7 @@
 class DownmixSw final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const Downmix::Capability kCapability;
+    static const Capability kCapability;
     static const Descriptor kDescriptor;
     DownmixSw() { LOG(DEBUG) << __func__; }
     ~DownmixSw() {
diff --git a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
index 0ffbaa1..da6d0c6 100644
--- a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
+++ b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
@@ -61,8 +61,33 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string DynamicsProcessingSw::kEffectName = "DynamicsProcessingSw";
-const DynamicsProcessing::Capability DynamicsProcessingSw::kCapability = {.minCutOffFreq = 220,
-                                                                          .maxCutOffFreq = 20000};
+const DynamicsProcessing::EqBandConfig DynamicsProcessingSw::kEqBandConfigMin =
+        DynamicsProcessing::EqBandConfig({.channel = 0,
+                                          .band = 0,
+                                          .enable = false,
+                                          .cutoffFrequencyHz = 220,
+                                          .gainDb = std::numeric_limits<float>::min()});
+const DynamicsProcessing::EqBandConfig DynamicsProcessingSw::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 DynamicsProcessingSw::kPreEqBandRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
+                {DynamicsProcessingSw::kEqBandConfigMin}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
+                {DynamicsProcessingSw::kEqBandConfigMax})};
+const Range::DynamicsProcessingRange DynamicsProcessingSw::kPostEqBandRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
+                {DynamicsProcessingSw::kEqBandConfigMin}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
+                {DynamicsProcessingSw::kEqBandConfigMax})};
+
+const std::vector<Range::DynamicsProcessingRange> DynamicsProcessingSw::kRanges = {
+        DynamicsProcessingSw::kPreEqBandRange, DynamicsProcessingSw::kPostEqBandRange};
+const Capability DynamicsProcessingSw::kCapability = {.range = DynamicsProcessingSw::kRanges};
+
 const Descriptor DynamicsProcessingSw::kDescriptor = {
         .common = {.id = {.type = kDynamicsProcessingTypeUUID,
                           .uuid = kDynamicsProcessingSwImplUUID,
@@ -72,8 +97,7 @@
                              .volume = Flags::Volume::CTRL},
                    .name = DynamicsProcessingSw::kEffectName,
                    .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::dynamicsProcessing>(
-                DynamicsProcessingSw::kCapability)};
+        .capability = DynamicsProcessingSw::kCapability};
 
 ndk::ScopedAStatus DynamicsProcessingSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
@@ -341,7 +365,6 @@
             LOG(WARNING) << __func__ << " skip invalid band " << cfg.toString();
             ret = RetCode::ERROR_ILLEGAL_PARAMETER;
             continue;
-            ;
         }
         targetCfgs[cfg.channel * stage.bandCount + cfg.band] = cfg;
     }
@@ -380,7 +403,6 @@
             LOG(WARNING) << __func__ << " skip invalid band " << it.toString();
             ret = RetCode::ERROR_ILLEGAL_PARAMETER;
             continue;
-            ;
         }
         mMbcChBands[it.channel * bandCount + it.band] = it;
     }
@@ -462,11 +484,6 @@
     return ret;
 }
 
-bool DynamicsProcessingSwContext::validateCutoffFrequency(float freq) {
-    return freq >= DynamicsProcessingSw::kCapability.minCutOffFreq &&
-           freq <= DynamicsProcessingSw::kCapability.maxCutOffFreq;
-}
-
 bool DynamicsProcessingSwContext::validateStageEnablement(
         const DynamicsProcessing::StageEnablement& enablement) {
     return !enablement.inUse || (enablement.inUse && enablement.bandCount > 0);
@@ -484,7 +501,7 @@
         const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
     return band.channel >= 0 && band.channel < maxChannel &&
            (size_t)band.channel < channelConfig.size() && channelConfig[band.channel].enable &&
-           band.band >= 0 && band.band < maxBand && validateCutoffFrequency(band.cutoffFrequencyHz);
+           band.band >= 0 && band.band < maxBand;
 }
 
 bool DynamicsProcessingSwContext::validateMbcBandConfig(
@@ -492,8 +509,7 @@
         const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
     return band.channel >= 0 && band.channel < maxChannel &&
            (size_t)band.channel < channelConfig.size() && channelConfig[band.channel].enable &&
-           band.band >= 0 && band.band < maxBand &&
-           validateCutoffFrequency(band.cutoffFrequencyHz) && band.attackTimeMs >= 0 &&
+           band.band >= 0 && band.band < maxBand && band.attackTimeMs >= 0 &&
            band.releaseTimeMs >= 0 && band.ratio >= 0 && band.thresholdDb <= 0 &&
            band.kneeWidthDb <= 0 && band.noiseGateThresholdDb <= 0 && band.expanderRatio >= 0;
 }
diff --git a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
index e336df7..3e14cce 100644
--- a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
+++ b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
@@ -86,8 +86,6 @@
     std::vector<DynamicsProcessing::EqBandConfig> mPreEqChBands;
     std::vector<DynamicsProcessing::EqBandConfig> mPostEqChBands;
     std::vector<DynamicsProcessing::MbcBandConfig> mMbcChBands;
-
-    bool validateCutoffFrequency(float freq);
     bool validateStageEnablement(const DynamicsProcessing::StageEnablement& enablement);
     bool validateEngineConfig(const DynamicsProcessing::EngineArchitecture& engine);
     bool validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band, int maxChannel,
@@ -104,7 +102,7 @@
 class DynamicsProcessingSw final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const DynamicsProcessing::Capability kCapability;
+    static const Capability kCapability;
     static const Descriptor kDescriptor;
     DynamicsProcessingSw() { LOG(DEBUG) << __func__; }
     ~DynamicsProcessingSw() {
@@ -125,6 +123,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 std::vector<Range::DynamicsProcessingRange> kRanges;
     std::shared_ptr<DynamicsProcessingSwContext> mContext;
     ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
                                                       Parameter::Specific* specific);
diff --git a/audio/aidl/default/envReverb/EnvReverbSw.cpp b/audio/aidl/default/envReverb/EnvReverbSw.cpp
index 905dba4..46d9016 100644
--- a/audio/aidl/default/envReverb/EnvReverbSw.cpp
+++ b/audio/aidl/default/envReverb/EnvReverbSw.cpp
@@ -60,18 +60,20 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string EnvReverbSw::kEffectName = "EnvReverbSw";
-const EnvironmentalReverb::Capability EnvReverbSw::kCapability = {.minRoomLevelMb = -6000,
-                                                                  .maxRoomLevelMb = 0,
-                                                                  .minRoomHfLevelMb = -4000,
-                                                                  .maxRoomHfLevelMb = 0,
-                                                                  .maxDecayTimeMs = 7000,
-                                                                  .minDecayHfRatioPm = 100,
-                                                                  .maxDecayHfRatioPm = 2000,
-                                                                  .minLevelMb = -6000,
-                                                                  .maxLevelMb = 0,
-                                                                  .maxDelayMs = 65,
-                                                                  .maxDiffusionPm = 1000,
-                                                                  .maxDensityPm = 1000};
+
+const std::vector<Range::EnvironmentalReverbRange> EnvReverbSw::kRanges = {
+        MAKE_RANGE(EnvironmentalReverb, roomLevelMb, -6000, 0),
+        MAKE_RANGE(EnvironmentalReverb, roomHfLevelMb, -4000, 0),
+        MAKE_RANGE(EnvironmentalReverb, decayTimeMs, 0, 7000),
+        MAKE_RANGE(EnvironmentalReverb, decayHfRatioPm, 100, 2000),
+        MAKE_RANGE(EnvironmentalReverb, levelMb, -6000, 0),
+        MAKE_RANGE(EnvironmentalReverb, delayMs, 0, 65),
+        MAKE_RANGE(EnvironmentalReverb, diffusionPm, 0, 1000),
+        MAKE_RANGE(EnvironmentalReverb, densityPm, 0, 1000)};
+
+const Capability EnvReverbSw::kCapability = {
+        .range = Range::make<Range::environmentalReverb>(EnvReverbSw::kRanges)};
+
 const Descriptor EnvReverbSw::kDescriptor = {
         .common = {.id = {.type = kEnvReverbTypeUUID,
                           .uuid = kEnvReverbSwImplUUID,
@@ -81,7 +83,7 @@
                              .volume = Flags::Volume::CTRL},
                    .name = EnvReverbSw::kEffectName,
                    .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::environmentalReverb>(EnvReverbSw::kCapability)};
+        .capability = EnvReverbSw::kCapability};
 
 ndk::ScopedAStatus EnvReverbSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
@@ -94,8 +96,8 @@
               "EffectNotSupported");
 
     auto& erParam = specific.get<Parameter::Specific::environmentalReverb>();
+    RETURN_IF(!inRange(erParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto tag = erParam.getTag();
-
     switch (tag) {
         case EnvironmentalReverb::roomLevelMb: {
             RETURN_IF(mContext->setErRoomLevel(erParam.get<EnvironmentalReverb::roomLevelMb>()) !=
@@ -262,85 +264,41 @@
 }
 
 RetCode EnvReverbSwContext::setErRoomLevel(int roomLevel) {
-    if (roomLevel < EnvReverbSw::kCapability.minRoomLevelMb ||
-        roomLevel > EnvReverbSw::kCapability.maxRoomLevelMb) {
-        LOG(ERROR) << __func__ << " invalid roomLevel: " << roomLevel;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-    // TODO : Add implementation to apply new room level
     mRoomLevel = roomLevel;
     return RetCode::SUCCESS;
 }
 
 RetCode EnvReverbSwContext::setErRoomHfLevel(int roomHfLevel) {
-    if (roomHfLevel < EnvReverbSw::kCapability.minRoomHfLevelMb ||
-        roomHfLevel > EnvReverbSw::kCapability.maxRoomHfLevelMb) {
-        LOG(ERROR) << __func__ << " invalid roomHfLevel: " << roomHfLevel;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-    // TODO : Add implementation to apply new room HF level
     mRoomHfLevel = roomHfLevel;
     return RetCode::SUCCESS;
 }
 
 RetCode EnvReverbSwContext::setErDecayTime(int decayTime) {
-    if (decayTime < 0 || decayTime > EnvReverbSw::kCapability.maxDecayTimeMs) {
-        LOG(ERROR) << __func__ << " invalid decayTime: " << decayTime;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-    // TODO : Add implementation to apply new decay time
     mDecayTime = decayTime;
     return RetCode::SUCCESS;
 }
 
 RetCode EnvReverbSwContext::setErDecayHfRatio(int decayHfRatio) {
-    if (decayHfRatio < EnvReverbSw::kCapability.minDecayHfRatioPm ||
-        decayHfRatio > EnvReverbSw::kCapability.maxDecayHfRatioPm) {
-        LOG(ERROR) << __func__ << " invalid decayHfRatio: " << decayHfRatio;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-    // TODO : Add implementation to apply new decay HF ratio
     mDecayHfRatio = decayHfRatio;
     return RetCode::SUCCESS;
 }
 
 RetCode EnvReverbSwContext::setErLevel(int level) {
-    if (level < EnvReverbSw::kCapability.minLevelMb ||
-        level > EnvReverbSw::kCapability.maxLevelMb) {
-        LOG(ERROR) << __func__ << " invalid level: " << level;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-    // TODO : Add implementation to apply new level
     mLevel = level;
     return RetCode::SUCCESS;
 }
 
 RetCode EnvReverbSwContext::setErDelay(int delay) {
-    if (delay < 0 || delay > EnvReverbSw::kCapability.maxDelayMs) {
-        LOG(ERROR) << __func__ << " invalid delay: " << delay;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-    // TODO : Add implementation to apply new delay
     mDelay = delay;
     return RetCode::SUCCESS;
 }
 
 RetCode EnvReverbSwContext::setErDiffusion(int diffusion) {
-    if (diffusion < 0 || diffusion > EnvReverbSw::kCapability.maxDiffusionPm) {
-        LOG(ERROR) << __func__ << " invalid diffusion: " << diffusion;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-    // TODO : Add implementation to apply new diffusion
     mDiffusion = diffusion;
     return RetCode::SUCCESS;
 }
 
 RetCode EnvReverbSwContext::setErDensity(int density) {
-    if (density < 0 || density > EnvReverbSw::kCapability.maxDensityPm) {
-        LOG(ERROR) << __func__ << " invalid density: " << density;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-    // TODO : Add implementation to apply new density
     mDensity = density;
     return RetCode::SUCCESS;
 }
diff --git a/audio/aidl/default/envReverb/EnvReverbSw.h b/audio/aidl/default/envReverb/EnvReverbSw.h
index 77f384e..4f11a5c 100644
--- a/audio/aidl/default/envReverb/EnvReverbSw.h
+++ b/audio/aidl/default/envReverb/EnvReverbSw.h
@@ -79,7 +79,7 @@
 class EnvReverbSw final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const EnvironmentalReverb::Capability kCapability;
+    static const Capability kCapability;
     static const Descriptor kDescriptor;
     EnvReverbSw() { LOG(DEBUG) << __func__; }
     ~EnvReverbSw() {
@@ -100,6 +100,7 @@
     std::string getEffectName() override { return kEffectName; }
 
   private:
+    static const std::vector<Range::EnvironmentalReverbRange> kRanges;
     std::shared_ptr<EnvReverbSwContext> mContext;
     ndk::ScopedAStatus getParameterEnvironmentalReverb(const EnvironmentalReverb::Tag& tag,
                                                        Parameter::Specific* specific);
diff --git a/audio/aidl/default/equalizer/EqualizerSw.cpp b/audio/aidl/default/equalizer/EqualizerSw.cpp
index 0a6ac34..2814322 100644
--- a/audio/aidl/default/equalizer/EqualizerSw.cpp
+++ b/audio/aidl/default/equalizer/EqualizerSw.cpp
@@ -60,6 +60,7 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string EqualizerSw::kEffectName = "EqualizerSw";
+
 const std::vector<Equalizer::BandFrequency> EqualizerSw::kBandFrequency = {{0, 30000, 120000},
                                                                            {1, 120001, 460000},
                                                                            {2, 460001, 1800000},
@@ -69,19 +70,34 @@
         {0, "Normal"},      {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
         {5, "Heavy Metal"}, {6, "Hip Hop"},   {7, "Jazz"},  {8, "Pop"},  {9, "Rock"}};
 
-const Equalizer::Capability EqualizerSw::kEqCap = {.bandFrequencies = kBandFrequency,
-                                                   .presets = kPresets};
+/**
+ * Use the same min and max to build a capability represented by Range.
+ */
+const std::vector<Range::EqualizerRange> EqualizerSw::kRanges = {
+        MAKE_RANGE(Equalizer, preset, 0, EqualizerSw::kPresets.size() - 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 = EqualizerSwContext::kMaxBandNumber - 1,
+                                                 .levelMb = std::numeric_limits<int>::max()})}),
+        /* capability definition */
+        MAKE_RANGE(Equalizer, bandFrequencies, EqualizerSw::kBandFrequency,
+                   EqualizerSw::kBandFrequency),
+        MAKE_RANGE(Equalizer, presets, EqualizerSw::kPresets, EqualizerSw::kPresets),
+        /* centerFreqMh is get only, set invalid range min > max */
+        MAKE_RANGE(Equalizer, centerFreqMh, std::vector<int>({1}), std::vector<int>({0}))};
 
-const Descriptor EqualizerSw::kDesc = {
-        .common = {.id = {.type = kEqualizerTypeUUID,
-                          .uuid = kEqualizerSwImplUUID,
-                          .proxy = kEqualizerProxyUUID},
-                   .flags = {.type = Flags::Type::INSERT,
-                             .insert = Flags::Insert::FIRST,
-                             .volume = Flags::Volume::CTRL},
-                   .name = EqualizerSw::kEffectName,
-                   .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::equalizer>(EqualizerSw::kEqCap)};
+const Capability EqualizerSw::kEqCap = {.range = EqualizerSw::kRanges};
+const Descriptor EqualizerSw::kDesc = {.common = {.id = {.type = kEqualizerTypeUUID,
+                                                         .uuid = kEqualizerSwImplUUID,
+                                                         .proxy = kEqualizerProxyUUID},
+                                                  .flags = {.type = Flags::Type::INSERT,
+                                                            .insert = Flags::Insert::FIRST,
+                                                            .volume = Flags::Volume::CTRL},
+                                                  .name = EqualizerSw::kEffectName,
+                                                  .implementor = "The Android Open Source Project"},
+                                       .capability = EqualizerSw::kEqCap};
 
 ndk::ScopedAStatus EqualizerSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDesc.toString();
@@ -95,6 +111,7 @@
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     auto& eqParam = specific.get<Parameter::Specific::equalizer>();
+    RETURN_IF(!inRange(eqParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto tag = eqParam.getTag();
     switch (tag) {
         case Equalizer::preset: {
diff --git a/audio/aidl/default/equalizer/EqualizerSw.h b/audio/aidl/default/equalizer/EqualizerSw.h
index fabcfeb..f8987c7 100644
--- a/audio/aidl/default/equalizer/EqualizerSw.h
+++ b/audio/aidl/default/equalizer/EqualizerSw.h
@@ -34,7 +34,7 @@
     }
 
     RetCode setEqPreset(const int& presetIdx) {
-        if (presetIdx < 0 || presetIdx >= NUM_OF_PRESETS) {
+        if (presetIdx < 0 || presetIdx >= kMaxPresetNumber) {
             return RetCode::ERROR_ILLEGAL_PARAMETER;
         }
         mPreset = presetIdx;
@@ -43,13 +43,13 @@
     int getEqPreset() { return mPreset; }
 
     RetCode setEqBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels) {
-        if (bandLevels.size() > NUM_OF_BANDS) {
-            LOG(ERROR) << __func__ << " return because size exceed " << NUM_OF_BANDS;
+        if (bandLevels.size() > kMaxBandNumber) {
+            LOG(ERROR) << __func__ << " return because size exceed " << kMaxBandNumber;
             return RetCode::ERROR_ILLEGAL_PARAMETER;
         }
         RetCode ret = RetCode::SUCCESS;
         for (auto& it : bandLevels) {
-            if (it.index >= NUM_OF_BANDS || it.index < 0) {
+            if (it.index >= kMaxBandNumber || it.index < 0) {
                 LOG(ERROR) << __func__ << " index illegal, skip: " << it.index << " - "
                            << it.levelMb;
                 ret = RetCode::ERROR_ILLEGAL_PARAMETER;
@@ -62,7 +62,7 @@
 
     std::vector<Equalizer::BandLevel> getEqBandLevels() {
         std::vector<Equalizer::BandLevel> bandLevels;
-        for (int i = 0; i < NUM_OF_BANDS; i++) {
+        for (int i = 0; i < kMaxBandNumber; i++) {
             bandLevels.push_back({i, mBandLevels[i]});
         }
         return bandLevels;
@@ -71,16 +71,16 @@
     std::vector<int> getCenterFreqs() {
         return {std::begin(kPresetsFrequencies), std::end(kPresetsFrequencies)};
     }
+    static const int kMaxBandNumber = 5;
+    static const int kMaxPresetNumber = 10;
+    static const int kCustomPreset = -1;
 
   private:
-    static const int NUM_OF_BANDS = 5;
-    static const int NUM_OF_PRESETS = 10;
-    static const int PRESET_CUSTOM = -1;
-    static constexpr std::array<uint16_t, NUM_OF_BANDS> kPresetsFrequencies = {60, 230, 910, 3600,
-                                                                               14000};
+    static constexpr std::array<uint16_t, kMaxBandNumber> kPresetsFrequencies = {60, 230, 910, 3600,
+                                                                                 14000};
     // preset band level
-    int mPreset = PRESET_CUSTOM;
-    int32_t mBandLevels[NUM_OF_BANDS] = {3, 0, 0, 0, 3};
+    int mPreset = kCustomPreset;
+    int32_t mBandLevels[kMaxBandNumber] = {3, 0, 0, 0, 3};
 
     // Add equalizer specific context for processing here
 };
@@ -88,9 +88,7 @@
 class EqualizerSw final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const std::vector<Equalizer::BandFrequency> kBandFrequency;
-    static const std::vector<Equalizer::Preset> kPresets;
-    static const Equalizer::Capability kEqCap;
+    static const Capability kEqCap;
     static const Descriptor kDesc;
 
     EqualizerSw() { LOG(DEBUG) << __func__; }
@@ -112,6 +110,9 @@
     std::string getEffectName() override { return kEffectName; }
 
   private:
+    static const std::vector<Equalizer::BandFrequency> kBandFrequency;
+    static const std::vector<Equalizer::Preset> kPresets;
+    static const std::vector<Range::EqualizerRange> kRanges;
     ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
                                              Parameter::Specific* specific);
     std::shared_ptr<EqualizerSwContext> mContext;
diff --git a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
index 3c3b66f..6037ad2 100644
--- a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
+++ b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
@@ -60,8 +60,6 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string HapticGeneratorSw::kEffectName = "HapticGeneratorSw";
-/* capabilities */
-const HapticGenerator::Capability HapticGeneratorSw::kCapability;
 /* Effect descriptor */
 const Descriptor HapticGeneratorSw::kDescriptor = {
         .common = {.id = {.type = kHapticGeneratorTypeUUID,
@@ -71,9 +69,7 @@
                              .insert = Flags::Insert::FIRST,
                              .volume = Flags::Volume::CTRL},
                    .name = HapticGeneratorSw::kEffectName,
-                   .implementor = "The Android Open Source Project"},
-        .capability =
-                Capability::make<Capability::hapticGenerator>(HapticGeneratorSw::kCapability)};
+                   .implementor = "The Android Open Source Project"}};
 
 ndk::ScopedAStatus HapticGeneratorSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
diff --git a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
index 7159501..428f460 100644
--- a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
+++ b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
@@ -58,7 +58,6 @@
 class HapticGeneratorSw final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const HapticGenerator::Capability kCapability;
     static const Descriptor kDescriptor;
     HapticGeneratorSw() { LOG(DEBUG) << __func__; }
     ~HapticGeneratorSw() {
diff --git a/audio/aidl/default/include/effect-impl/EffectTypes.h b/audio/aidl/default/include/effect-impl/EffectTypes.h
index b100a2e..fe534d7 100644
--- a/audio/aidl/default/include/effect-impl/EffectTypes.h
+++ b/audio/aidl/default/include/effect-impl/EffectTypes.h
@@ -19,16 +19,18 @@
 #include <string>
 
 #include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <aidl/android/hardware/audio/effect/Range.h>
 #include <android-base/logging.h>
+#include <system/audio_effects/aidl_effects_utils.h>
 
 typedef binder_exception_t (*EffectCreateFunctor)(
         const ::aidl::android::media::audio::common::AudioUuid*,
-        std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>*);
+        std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>*);
 typedef binder_exception_t (*EffectDestroyFunctor)(
-        const std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>&);
+        const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&);
 typedef binder_exception_t (*EffectQueryFunctor)(
         const ::aidl::android::media::audio::common::AudioUuid*,
-        aidl::android::hardware::audio::effect::Descriptor*);
+        ::aidl::android::hardware::audio::effect::Descriptor*);
 
 struct effect_dl_interface_s {
     EffectCreateFunctor createEffectFunc;
@@ -116,6 +118,16 @@
         }                                                                   \
     }
 
+/**
+ * Make a Range::$EffectType$Range.
+ * T: The $EffectType$, Visualizer for example.
+ * Tag: The union tag name in $EffectType$ definition, latencyMs for example.
+ * l: The value of Range::$EffectType$Range.min.
+ * r: The value of Range::$EffectType$Range.max.
+ */
+#define MAKE_RANGE(T, Tag, l, r) \
+    { .min = T::make<T::Tag>(l), .max = T::make<T::Tag>(r) }
+
 static inline bool stringToUuid(const char* str,
                                 ::aidl::android::media::audio::common::AudioUuid* uuid) {
     RETURN_VALUE_IF(!uuid || !str, false, "nullPtr");
diff --git a/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h
index 5da70c7..e252f4a 100644
--- a/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h
+++ b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h
@@ -47,7 +47,6 @@
 class LoudnessEnhancerSw final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const LoudnessEnhancer::Capability kCapability;
     static const Descriptor kDescriptor;
     LoudnessEnhancerSw() { LOG(DEBUG) << __func__; }
     ~LoudnessEnhancerSw() {
diff --git a/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp
index 51fe4ea..0ea31ea 100644
--- a/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp
+++ b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp
@@ -60,7 +60,6 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string NoiseSuppressionSw::kEffectName = "NoiseSuppressionSw";
-const NoiseSuppression::Capability NoiseSuppressionSw::kCapability;
 const Descriptor NoiseSuppressionSw::kDescriptor = {
         .common = {.id = {.type = kNoiseSuppressionTypeUUID,
                           .uuid = kNoiseSuppressionSwImplUUID,
@@ -69,9 +68,7 @@
                              .insert = Flags::Insert::FIRST,
                              .volume = Flags::Volume::CTRL},
                    .name = NoiseSuppressionSw::kEffectName,
-                   .implementor = "The Android Open Source Project"},
-        .capability =
-                Capability::make<Capability::noiseSuppression>(NoiseSuppressionSw::kCapability)};
+                   .implementor = "The Android Open Source Project"}};
 
 ndk::ScopedAStatus NoiseSuppressionSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
diff --git a/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.h b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.h
index a851e38..22bf066 100644
--- a/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.h
+++ b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.h
@@ -47,7 +47,6 @@
   public:
     static const std::string kEffectName;
     static const bool kStrengthSupported;
-    static const NoiseSuppression::Capability kCapability;
     static const Descriptor kDescriptor;
     NoiseSuppressionSw() { LOG(DEBUG) << __func__; }
     ~NoiseSuppressionSw() {
diff --git a/audio/aidl/default/presetReverb/PresetReverbSw.cpp b/audio/aidl/default/presetReverb/PresetReverbSw.cpp
index d038596..2da3ff6 100644
--- a/audio/aidl/default/presetReverb/PresetReverbSw.cpp
+++ b/audio/aidl/default/presetReverb/PresetReverbSw.cpp
@@ -62,12 +62,17 @@
 
 const std::string PresetReverbSw::kEffectName = "PresetReverbSw";
 
-const std::vector<PresetReverb::Presets> kSupportedPresets{
+const std::vector<PresetReverb::Presets> PresetReverbSw::kSupportedPresets{
         ndk::enum_range<PresetReverb::Presets>().begin(),
         ndk::enum_range<PresetReverb::Presets>().end()};
 
-const PresetReverb::Capability PresetReverbSw::kCapability = {.supportedPresets =
-                                                                      kSupportedPresets};
+const std::vector<Range::PresetReverbRange> PresetReverbSw::kRanges = {
+        MAKE_RANGE(PresetReverb, supportedPresets, PresetReverbSw::kSupportedPresets,
+                   PresetReverbSw::kSupportedPresets)};
+
+const Capability PresetReverbSw::kCapability = {
+        .range = Range::make<Range::presetReverb>(PresetReverbSw::kRanges)};
+
 const Descriptor PresetReverbSw::kDescriptor = {
         .common = {.id = {.type = kPresetReverbTypeUUID,
                           .uuid = kPresetReverbSwImplUUID,
@@ -77,7 +82,7 @@
                              .volume = Flags::Volume::CTRL},
                    .name = PresetReverbSw::kEffectName,
                    .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::presetReverb>(PresetReverbSw::kCapability)};
+        .capability = PresetReverbSw::kCapability};
 
 ndk::ScopedAStatus PresetReverbSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
@@ -92,6 +97,7 @@
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     auto& prParam = specific.get<Parameter::Specific::presetReverb>();
+    RETURN_IF(!inRange(prParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto tag = prParam.getTag();
 
     switch (tag) {
diff --git a/audio/aidl/default/presetReverb/PresetReverbSw.h b/audio/aidl/default/presetReverb/PresetReverbSw.h
index eb1d80a..5061475 100644
--- a/audio/aidl/default/presetReverb/PresetReverbSw.h
+++ b/audio/aidl/default/presetReverb/PresetReverbSw.h
@@ -46,7 +46,9 @@
 class PresetReverbSw final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const PresetReverb::Capability kCapability;
+    static const std::vector<PresetReverb::Presets> kSupportedPresets;
+    static const std::vector<Range::PresetReverbRange> kRanges;
+    static const Capability kCapability;
     static const Descriptor kDescriptor;
     PresetReverbSw() { LOG(DEBUG) << __func__; }
     ~PresetReverbSw() {
diff --git a/audio/aidl/default/virtualizer/VirtualizerSw.cpp b/audio/aidl/default/virtualizer/VirtualizerSw.cpp
index 08535bd..5e99cba2 100644
--- a/audio/aidl/default/virtualizer/VirtualizerSw.cpp
+++ b/audio/aidl/default/virtualizer/VirtualizerSw.cpp
@@ -32,6 +32,7 @@
 using aidl::android::hardware::audio::effect::VirtualizerSw;
 using aidl::android::media::audio::common::AudioChannelLayout;
 using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
 using aidl::android::media::audio::common::AudioUuid;
 
 extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
@@ -62,9 +63,20 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string VirtualizerSw::kEffectName = "VirtualizerSw";
-const bool VirtualizerSw::kStrengthSupported = true;
-const Virtualizer::Capability VirtualizerSw::kCapability = {
-        .maxStrengthPm = 1000, .strengthSupported = kStrengthSupported};
+
+const std::vector<Range::VirtualizerRange> VirtualizerSw::kRanges = {
+        MAKE_RANGE(Virtualizer, strengthPm, 0, 1000),
+        /* speakerAngle is get-only, set min > max */
+        MAKE_RANGE(Virtualizer, speakerAngles, {Virtualizer::ChannelAngle({.channel = 1})},
+                   {Virtualizer::ChannelAngle({.channel = 0})}),
+        /* device is get-only */
+        MAKE_RANGE(Virtualizer, device,
+                   AudioDeviceDescription({.type = AudioDeviceType::IN_DEFAULT}),
+                   AudioDeviceDescription({.type = AudioDeviceType::NONE}))};
+
+const Capability VirtualizerSw::kCapability = {
+        .range = Range::make<Range::virtualizer>(VirtualizerSw::kRanges)};
+
 const Descriptor VirtualizerSw::kDescriptor = {
         .common = {.id = {.type = kVirtualizerTypeUUID,
                           .uuid = kVirtualizerSwImplUUID,
@@ -74,7 +86,7 @@
                              .volume = Flags::Volume::CTRL},
                    .name = VirtualizerSw::kEffectName,
                    .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::virtualizer>(VirtualizerSw::kCapability)};
+        .capability = VirtualizerSw::kCapability};
 
 ndk::ScopedAStatus VirtualizerSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
@@ -87,12 +99,11 @@
               "EffectNotSupported");
 
     auto& vrParam = specific.get<Parameter::Specific::virtualizer>();
+    RETURN_IF(!inRange(vrParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto tag = vrParam.getTag();
 
     switch (tag) {
         case Virtualizer::strengthPm: {
-            RETURN_IF(!kStrengthSupported, EX_ILLEGAL_ARGUMENT, "SettingStrengthNotSupported");
-
             RETURN_IF(mContext->setVrStrength(vrParam.get<Virtualizer::strengthPm>()) !=
                               RetCode::SUCCESS,
                       EX_ILLEGAL_ARGUMENT, "setStrengthPmFailed");
@@ -213,11 +224,6 @@
 }
 
 RetCode VirtualizerSwContext::setVrStrength(int strength) {
-    if (strength < 0 || strength > VirtualizerSw::kCapability.maxStrengthPm) {
-        LOG(ERROR) << __func__ << " invalid strength: " << strength;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-    // TODO : Add implementation to apply new strength
     mStrength = strength;
     return RetCode::SUCCESS;
 }
diff --git a/audio/aidl/default/virtualizer/VirtualizerSw.h b/audio/aidl/default/virtualizer/VirtualizerSw.h
index 1016ffc..5c5b616 100644
--- a/audio/aidl/default/virtualizer/VirtualizerSw.h
+++ b/audio/aidl/default/virtualizer/VirtualizerSw.h
@@ -51,8 +51,7 @@
 class VirtualizerSw final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const bool kStrengthSupported;
-    static const Virtualizer::Capability kCapability;
+    static const Capability kCapability;
     static const Descriptor kDescriptor;
     VirtualizerSw() { LOG(DEBUG) << __func__; }
     ~VirtualizerSw() {
@@ -73,6 +72,7 @@
     std::string getEffectName() override { return kEffectName; }
 
   private:
+    static const std::vector<Range::VirtualizerRange> kRanges;
     std::shared_ptr<VirtualizerSwContext> mContext;
 
     ndk::ScopedAStatus getParameterVirtualizer(const Virtualizer::Tag& tag,
diff --git a/audio/aidl/default/visualizer/VisualizerSw.cpp b/audio/aidl/default/visualizer/VisualizerSw.cpp
index 614988c..deb3204 100644
--- a/audio/aidl/default/visualizer/VisualizerSw.cpp
+++ b/audio/aidl/default/visualizer/VisualizerSw.cpp
@@ -55,12 +55,15 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string VisualizerSw::kEffectName = "VisualizerSw";
+
 /* capabilities */
-const Visualizer::CaptureSamplesRange VisualizerSwContext::kCaptureSamplesRange = {
-        VisualizerSwContext::kMinCaptureSize, VisualizerSwContext::kMaxCaptureSize};
-const Visualizer::Capability VisualizerSw::kCapability = {
-        .maxLatencyMs = VisualizerSwContext::kMaxLatencyMs,
-        .captureSampleRange = VisualizerSwContext::kCaptureSamplesRange};
+const std::vector<Range::VisualizerRange> VisualizerSw::kRanges = {
+        MAKE_RANGE(Visualizer, latencyMs, 0, VisualizerSwContext::kMaxLatencyMs),
+        MAKE_RANGE(Visualizer, captureSamples, VisualizerSwContext::kMinCaptureSize,
+                   VisualizerSwContext::kMaxCaptureSize)};
+
+const Capability VisualizerSw::kCapability = {
+        .range = Range::make<Range::visualizer>(VisualizerSw::kRanges)};
 
 const Descriptor VisualizerSw::kDescriptor = {
         .common = {.id = {.type = kVisualizerTypeUUID,
@@ -71,7 +74,7 @@
                              .volume = Flags::Volume::CTRL},
                    .name = VisualizerSw::kEffectName,
                    .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::visualizer>(VisualizerSw::kCapability)};
+        .capability = VisualizerSw::kCapability};
 
 ndk::ScopedAStatus VisualizerSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
@@ -84,34 +87,33 @@
               "EffectNotSupported");
 
     auto& vsParam = specific.get<Parameter::Specific::visualizer>();
+    RETURN_IF(!inRange(vsParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto tag = vsParam.getTag();
 
     switch (tag) {
         case Visualizer::captureSamples: {
             RETURN_IF(mContext->setVsCaptureSize(vsParam.get<Visualizer::captureSamples>()) !=
                               RetCode::SUCCESS,
-                      EX_ILLEGAL_ARGUMENT, "captureSizeNotSupported");
+                      EX_ILLEGAL_ARGUMENT, "setCaptureSizeFailed");
             return ndk::ScopedAStatus::ok();
         }
         case Visualizer::scalingMode: {
             RETURN_IF(mContext->setVsScalingMode(vsParam.get<Visualizer::scalingMode>()) !=
                               RetCode::SUCCESS,
-                      EX_ILLEGAL_ARGUMENT, "scalingModeNotSupported");
+                      EX_ILLEGAL_ARGUMENT, "setScalingModeFailed");
             return ndk::ScopedAStatus::ok();
         }
         case Visualizer::measurementMode: {
             RETURN_IF(mContext->setVsMeasurementMode(vsParam.get<Visualizer::measurementMode>()) !=
                               RetCode::SUCCESS,
-                      EX_ILLEGAL_ARGUMENT, "measurementModeNotSupported");
+                      EX_ILLEGAL_ARGUMENT, "setMeasurementModeFailed");
             return ndk::ScopedAStatus::ok();
         }
-        case Visualizer::setOnlyParameters: {
-            return setSetOnlyParameterVisualizer(vsParam.get<Visualizer::setOnlyParameters>());
-        }
-        case Visualizer::getOnlyParameters: {
-            LOG(ERROR) << __func__ << " unsupported settable getOnlyParam";
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
-                    EX_ILLEGAL_ARGUMENT, "SetofGetOnlyParamsNotSupported");
+        case Visualizer::latencyMs: {
+            RETURN_IF(mContext->setVsLatency(vsParam.get<Visualizer::latencyMs>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setLatencyFailed");
+            return ndk::ScopedAStatus::ok();
         }
         default: {
             LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
@@ -121,18 +123,6 @@
     }
 }
 
-ndk::ScopedAStatus VisualizerSw::setSetOnlyParameterVisualizer(
-        Visualizer::SetOnlyParameters setOnlyParam) {
-    auto tag = setOnlyParam.getTag();
-    RETURN_IF(Visualizer::SetOnlyParameters::latencyMs != tag, EX_ILLEGAL_ARGUMENT,
-              "SetOnlyParametersTagNotSupported");
-    RETURN_IF(
-            mContext->setVsLatency(setOnlyParam.get<Visualizer::SetOnlyParameters::latencyMs>()) !=
-                    RetCode::SUCCESS,
-            EX_ILLEGAL_ARGUMENT, "latencyNotSupported");
-    return ndk::ScopedAStatus::ok();
-}
-
 ndk::ScopedAStatus VisualizerSw::getParameterSpecific(const Parameter::Id& id,
                                                       Parameter::Specific* specific) {
     auto tag = id.getTag();
@@ -142,14 +132,6 @@
     switch (vsIdTag) {
         case Visualizer::Id::commonTag:
             return getParameterVisualizer(vsId.get<Visualizer::Id::commonTag>(), specific);
-        case Visualizer::Id::getOnlyParamTag:
-            return getGetOnlyParameterVisualizer(vsId.get<Visualizer::Id::getOnlyParamTag>(),
-                                                 specific);
-        case Visualizer::Id::setOnlyParamTag: {
-            LOG(ERROR) << __func__ << " unsupported gettable setOnlyParam";
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
-                    EX_ILLEGAL_ARGUMENT, "GetofSetOnlyParamsNotSupported");
-        }
         default:
             LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
             return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
@@ -174,6 +156,18 @@
             vsParam.set<Visualizer::measurementMode>(mContext->getVsMeasurementMode());
             break;
         }
+        case Visualizer::measurement: {
+            vsParam.set<Visualizer::measurement>(mContext->getVsMeasurement());
+            break;
+        }
+        case Visualizer::captureSampleBuffer: {
+            vsParam.set<Visualizer::captureSampleBuffer>(mContext->getVsCaptureSampleBuffer());
+            break;
+        }
+        case Visualizer::latencyMs: {
+            vsParam.set<Visualizer::latencyMs>(mContext->getVsLatency());
+            break;
+        }
         default: {
             LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
             return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
@@ -184,32 +178,6 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus VisualizerSw::getGetOnlyParameterVisualizer(
-        const Visualizer::GetOnlyParameters::Tag& tag, Parameter::Specific* specific) {
-    Visualizer::GetOnlyParameters getOnlyParam;
-    switch (tag) {
-        case Visualizer::GetOnlyParameters::measurement: {
-            getOnlyParam.set<Visualizer::GetOnlyParameters::measurement>(
-                    mContext->getVsMeasurement());
-            break;
-        }
-        case Visualizer::GetOnlyParameters::captureSampleBuffer: {
-            getOnlyParam.set<Visualizer::GetOnlyParameters::captureSampleBuffer>(
-                    mContext->getVsCaptureSampleBuffer());
-            break;
-        }
-        default: {
-            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
-                    EX_ILLEGAL_ARGUMENT, "GetOnlyParameterTagNotSupported");
-        }
-    }
-    Visualizer vsParam;
-    vsParam.set<Visualizer::getOnlyParameters>(getOnlyParam);
-    specific->set<Parameter::Specific::visualizer>(vsParam);
-    return ndk::ScopedAStatus::ok();
-}
-
 std::shared_ptr<EffectContext> VisualizerSw::createContext(const Parameter::Common& common) {
     if (mContext) {
         LOG(DEBUG) << __func__ << " context already exist";
@@ -242,34 +210,21 @@
 }
 
 RetCode VisualizerSwContext::setVsCaptureSize(int captureSize) {
-    if (captureSize < VisualizerSw::kCapability.captureSampleRange.min ||
-        captureSize > VisualizerSw::kCapability.captureSampleRange.max) {
-        LOG(ERROR) << __func__ << " invalid captureSize " << captureSize;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-    // TODO : Add implementation to apply new captureSize
     mCaptureSize = captureSize;
     return RetCode::SUCCESS;
 }
 
 RetCode VisualizerSwContext::setVsScalingMode(Visualizer::ScalingMode scalingMode) {
-    // TODO : Add implementation to apply new scalingMode
     mScalingMode = scalingMode;
     return RetCode::SUCCESS;
 }
 
 RetCode VisualizerSwContext::setVsMeasurementMode(Visualizer::MeasurementMode measurementMode) {
-    // TODO : Add implementation to apply new measurementMode
     mMeasurementMode = measurementMode;
     return RetCode::SUCCESS;
 }
 
 RetCode VisualizerSwContext::setVsLatency(int latency) {
-    if (latency < 0 || latency > VisualizerSw::kCapability.maxLatencyMs) {
-        LOG(ERROR) << __func__ << " invalid latency " << latency;
-        return RetCode::ERROR_ILLEGAL_PARAMETER;
-    }
-    // TODO : Add implementation to modify latency
     mLatency = latency;
     return RetCode::SUCCESS;
 }
diff --git a/audio/aidl/default/visualizer/VisualizerSw.h b/audio/aidl/default/visualizer/VisualizerSw.h
index e9d46d7..ee7276a 100644
--- a/audio/aidl/default/visualizer/VisualizerSw.h
+++ b/audio/aidl/default/visualizer/VisualizerSw.h
@@ -30,7 +30,6 @@
     static const int kMaxCaptureSize = 0x400;
     static const int kMaxLatencyMs = 3000;
     static const int kMaxCaptureBufSize = 0xffff;
-    static const Visualizer::CaptureSamplesRange kCaptureSamplesRange;
     VisualizerSwContext(int statusDepth, const Parameter::Common& common)
         : EffectContext(statusDepth, common) {
         LOG(DEBUG) << __func__;
@@ -48,8 +47,9 @@
     Visualizer::MeasurementMode getVsMeasurementMode() const { return mMeasurementMode; }
 
     RetCode setVsLatency(int latency);
+    int getVsLatency() const { return mLatency; }
 
-    Visualizer::GetOnlyParameters::Measurement getVsMeasurement() const { return mMeasurement; }
+    Visualizer::Measurement getVsMeasurement() const { return mMeasurement; }
     std::vector<uint8_t> getVsCaptureSampleBuffer() const { return mCaptureSampleBuffer; }
 
   private:
@@ -57,14 +57,14 @@
     Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED;
     Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE;
     int mLatency = 0;
-    const Visualizer::GetOnlyParameters::Measurement mMeasurement = {0, 0};
+    const Visualizer::Measurement mMeasurement = {0, 0};
     std::vector<uint8_t> mCaptureSampleBuffer;
 };
 
 class VisualizerSw final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const Visualizer::Capability kCapability;
+    static const Capability kCapability;
     static const Descriptor kDescriptor;
     VisualizerSw() { LOG(DEBUG) << __func__; }
     ~VisualizerSw() {
@@ -85,12 +85,9 @@
     std::string getEffectName() override { return kEffectName; }
 
   private:
+    static const std::vector<Range::VisualizerRange> kRanges;
     std::shared_ptr<VisualizerSwContext> mContext;
-
-    ndk::ScopedAStatus setSetOnlyParameterVisualizer(Visualizer::SetOnlyParameters setOnlyParam);
     ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
                                               Parameter::Specific* specific);
-    ndk::ScopedAStatus getGetOnlyParameterVisualizer(const Visualizer::GetOnlyParameters::Tag& tag,
-                                                     Parameter::Specific* specific);
 };
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/volume/VolumeSw.cpp b/audio/aidl/default/volume/VolumeSw.cpp
index 64301dc..796c332 100644
--- a/audio/aidl/default/volume/VolumeSw.cpp
+++ b/audio/aidl/default/volume/VolumeSw.cpp
@@ -60,7 +60,11 @@
 namespace aidl::android::hardware::audio::effect {
 
 const std::string VolumeSw::kEffectName = "VolumeSw";
-const Volume::Capability VolumeSw::kCapability = {.minLevelDb = -9600, .maxLevelDb = 0};
+
+const std::vector<Range::VolumeRange> VolumeSw::kRanges = {MAKE_RANGE(Volume, levelDb, -9600, 0)};
+
+const Capability VolumeSw::kCapability = {.range = Range::make<Range::volume>(VolumeSw::kRanges)};
+
 const Descriptor VolumeSw::kDescriptor = {
         .common = {.id = {.type = kVolumeTypeUUID,
                           .uuid = kVolumeSwImplUUID,
@@ -70,7 +74,7 @@
                              .volume = Flags::Volume::CTRL},
                    .name = VolumeSw::kEffectName,
                    .implementor = "The Android Open Source Project"},
-        .capability = Capability::make<Capability::volume>(VolumeSw::kCapability)};
+        .capability = VolumeSw::kCapability};
 
 ndk::ScopedAStatus VolumeSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
@@ -83,6 +87,7 @@
               "EffectNotSupported");
 
     auto& volParam = specific.get<Parameter::Specific::volume>();
+    RETURN_IF(!inRange(volParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
     auto tag = volParam.getTag();
 
     switch (tag) {
@@ -177,11 +182,6 @@
 }
 
 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;
 }
diff --git a/audio/aidl/default/volume/VolumeSw.h b/audio/aidl/default/volume/VolumeSw.h
index b6f6077..2dd4324 100644
--- a/audio/aidl/default/volume/VolumeSw.h
+++ b/audio/aidl/default/volume/VolumeSw.h
@@ -49,7 +49,7 @@
 class VolumeSw final : public EffectImpl {
   public:
     static const std::string kEffectName;
-    static const Volume::Capability kCapability;
+    static const Capability kCapability;
     static const Descriptor kDescriptor;
     VolumeSw() { LOG(DEBUG) << __func__; }
     ~VolumeSw() {
@@ -70,6 +70,7 @@
     std::string getEffectName() override { return kEffectName; }
 
   private:
+    static const std::vector<Range::VolumeRange> kRanges;
     std::shared_ptr<VolumeSwContext> mContext;
 
     ndk::ScopedAStatus getParameterVolume(const Volume::Tag& tag, Parameter::Specific* specific);