Add VTS tests for audio effects

Added tests covering IEffect, IEqualizerEffect, and
ILoudnessEnhancer interfaces.

Minor corrections in the interface definitions and implementations:

 - fixed descriptions and @callflow annotations in IEffect;

 - fixed type used for band levels in IEqualizerEffect;

 - fixed specification of frequencies in IEqualizerEffect;

 - fixed some bugs in previously non-execrices Effects code;

 - warning messages changed to error messages.

Test: this is a test
Bug: 32022706
Change-Id: I0e0bc111b07d944ad8a0321e8b1ec703f8d1a73e
diff --git a/audio/effect/2.0/IEffect.hal b/audio/effect/2.0/IEffect.hal
index 9e10117..d254e8c 100644
--- a/audio/effect/2.0/IEffect.hal
+++ b/audio/effect/2.0/IEffect.hal
@@ -59,7 +59,7 @@
      *
      * @return retval operation completion status.
      */
-    @callflow(next={"process"})
+    @callflow(next={"prepareForProcessing"})
     enable() generates (Result retval);
 
     /*
@@ -67,7 +67,7 @@
      *
      * @return retval operation completion status.
      */
-    @exit
+    @callflow(next={"close"})
     disable() generates (Result retval);
 
     /*
@@ -75,6 +75,9 @@
      * effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its
      * descriptor to receive this command when the device changes.
      *
+     * Note: this method is only supported for effects inserted into
+     *       the output chain.
+     *
      * @param device output device specification.
      * @return retval operation completion status.
      */
@@ -145,6 +148,9 @@
      * implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to
      * receive this command when the device changes.
      *
+     * Note: this method is only supported for effects inserted into
+     *       the input chain.
+     *
      * @param device input device specification.
      * @return retval operation completion status.
      */
@@ -209,6 +215,9 @@
      * Set the audio source the capture path is configured for (Camcorder, voice
      * recognition...).
      *
+     * Note: this method is only supported for effects inserted into
+     *       the input chain.
+     *
      * @param source source descriptor.
      * @return retval operation completion status.
      */
@@ -258,6 +267,7 @@
      *                                  the queue.
      * @return statusMQ a message queue used for passing status from the effect.
      */
+    @callflow(next={"setProcessBuffers"})
     prepareForProcessing() generates (Result retval, fmq_sync<Result> statusMQ);
 
     /*
@@ -275,6 +285,7 @@
      *                INVALID_ARGUMENTS if there was a problem with mapping
      *                                  any of the buffers.
      */
+    @callflow(next={"*"})
     setProcessBuffers(AudioBuffer inBuffer, AudioBuffer outBuffer) generates (
             Result retval);
 
@@ -423,5 +434,6 @@
      * @return retval OK in case the success.
      *                INVALID_STATE if the effect was already closed.
      */
+    @exit
     close() generates (Result retval);
 };
diff --git a/audio/effect/2.0/IEqualizerEffect.hal b/audio/effect/2.0/IEqualizerEffect.hal
index afcc4b6..b8fa177 100644
--- a/audio/effect/2.0/IEqualizerEffect.hal
+++ b/audio/effect/2.0/IEqualizerEffect.hal
@@ -29,34 +29,36 @@
      * Returns the minimum and maximum band levels supported.
      */
     getLevelRange()
-            generates (Result retval, uint16_t minLevel, uint16_t maxLevel);
+            generates (Result retval, int16_t minLevel, int16_t maxLevel);
 
     /*
      * Sets the gain for the given equalizer band.
      */
-    setBandLevel(uint16_t band, uint16_t level) generates (Result retval);
+    setBandLevel(uint16_t band, int16_t level) generates (Result retval);
 
     /*
      * Gets the gain for the given equalizer band.
      */
-    getBandLevel(uint16_t band) generates (Result retval, uint16_t level);
+    getBandLevel(uint16_t band) generates (Result retval, int16_t level);
 
     /*
-     * Gets the center frequency of the given band.
+     * Gets the center frequency of the given band, in milliHertz.
      */
     getBandCenterFrequency(uint16_t band)
-            generates (Result retval, uint32_t centerFreq);
+            generates (Result retval, uint32_t centerFreqmHz);
 
     /*
-     * Gets the frequency range of the given frequency band.
+     * Gets the frequency range of the given frequency band, in milliHertz.
      */
     getBandFrequencyRange(uint16_t band)
-            generates (Result retval, uint32_t minFreqHz, uint32_t maxFreqHz);
+            generates (Result retval, uint32_t minFreqmHz, uint32_t maxFreqmHz);
 
     /*
-     * Gets the band that has the most effect on the given frequency.
+     * Gets the band that has the most effect on the given frequency
+     * in milliHertz.
      */
-    getBandForFrequency(uint32_t freq) generates (Result retval, uint16_t band);
+    getBandForFrequency(uint32_t freqmHz)
+            generates (Result retval, uint16_t band);
 
     /*
      * Gets the names of all presets the equalizer supports.
@@ -76,7 +78,7 @@
 
     struct AllProperties {
         uint16_t curPreset;
-        vec<uint16_t> bandLevels;
+        vec<int16_t> bandLevels;
     };
 
     /*
diff --git a/audio/effect/2.0/default/Effect.cpp b/audio/effect/2.0/default/Effect.cpp
index 83c8e09..6704239 100644
--- a/audio/effect/2.0/default/Effect.cpp
+++ b/audio/effect/2.0/default/Effect.cpp
@@ -188,6 +188,8 @@
 // static
 void Effect::effectBufferConfigFromHal(
         const buffer_config_t& halConfig, EffectBufferConfig* config) {
+    config->buffer.id = 0;
+    config->buffer.frameCount = 0;
     config->samplingRateHz = halConfig.samplingRate;
     config->channels = AudioChannelMask(halConfig.channels);
     config->format = AudioFormat(halConfig.format);
@@ -282,7 +284,7 @@
 
 void Effect::getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb) {
     uint32_t halResultSize = sizeof(effect_config_t);
-    effect_config_t halConfig;
+    effect_config_t halConfig{};
     status_t status = (*mHandle)->command(
             mHandle, commandCode, 0, NULL, &halResultSize, &halConfig);
     EffectConfig config;
@@ -309,15 +311,16 @@
 Result Effect::getParameterImpl(
         uint32_t paramSize,
         const void* paramData,
-        uint32_t valueSize,
+        uint32_t requestValueSize,
+        uint32_t replyValueSize,
         GetParameterSuccessCallback onSuccess) {
     // As it is unknown what method HAL uses for copying the provided parameter data,
     // it is safer to make sure that input and output buffers do not overlap.
     std::vector<uint8_t> halCmdBuffer =
-            parameterToHal(paramSize, paramData, valueSize, nullptr);
+            parameterToHal(paramSize, paramData, requestValueSize, nullptr);
     const void *valueData = nullptr;
     std::vector<uint8_t> halParamBuffer =
-            parameterToHal(paramSize, paramData, valueSize, &valueData);
+            parameterToHal(paramSize, paramData, replyValueSize, &valueData);
     uint32_t halParamBufferSize = halParamBuffer.size();
 
     return sendCommandReturningStatusAndData(
diff --git a/audio/effect/2.0/default/Effect.h b/audio/effect/2.0/default/Effect.h
index 13faec4..0918cd8 100644
--- a/audio/effect/2.0/default/Effect.h
+++ b/audio/effect/2.0/default/Effect.h
@@ -60,6 +60,8 @@
 
 struct Effect : public IEffect {
     typedef MessageQueue<Result, kSynchronizedReadWrite> StatusMQ;
+    using GetParameterSuccessCallback =
+            std::function<void(uint32_t valueSize, const void* valueData)>;
 
     explicit Effect(effect_handle_t handle);
 
@@ -163,6 +165,22 @@
         return setParameterImpl(sizeof(params), params, sizeof(T), &paramValue);
     }
 
+    Result getParameterImpl(
+            uint32_t paramSize,
+            const void* paramData,
+            uint32_t valueSize,
+            GetParameterSuccessCallback onSuccess) {
+        return getParameterImpl(paramSize, paramData, valueSize, valueSize, onSuccess);
+    }
+    Result getParameterImpl(
+            uint32_t paramSize,
+            const void* paramData,
+            uint32_t requestValueSize,
+            uint32_t replyValueSize,
+            GetParameterSuccessCallback onSuccess);
+    Result setParameterImpl(
+            uint32_t paramSize, const void* paramData, uint32_t valueSize, const void* valueData);
+
   private:
     friend struct VirtualizerEffect;  // for getParameterImpl
     friend struct VisualizerEffect;   // to allow executing commands
@@ -170,8 +188,6 @@
     using CommandSuccessCallback = std::function<void()>;
     using GetConfigCallback = std::function<void(Result retval, const EffectConfig& config)>;
     using GetCurrentConfigSuccessCallback = std::function<void(void* configData)>;
-    using GetParameterSuccessCallback =
-            std::function<void(uint32_t valueSize, const void* valueData)>;
     using GetSupportedConfigsSuccessCallback =
             std::function<void(uint32_t supportedConfigs, void* configsData)>;
 
@@ -220,11 +236,6 @@
     void getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb);
     Result getCurrentConfigImpl(
             uint32_t featureId, uint32_t configSize, GetCurrentConfigSuccessCallback onSuccess);
-    Result getParameterImpl(
-            uint32_t paramSize,
-            const void* paramData,
-            uint32_t valueSize,
-            GetParameterSuccessCallback onSuccess);
     Result getSupportedConfigsImpl(
             uint32_t featureId,
             uint32_t maxConfigs,
@@ -252,8 +263,6 @@
             const EffectConfig& config,
             const sp<IEffectBufferProviderCallback>& inputBufferProvider,
             const sp<IEffectBufferProviderCallback>& outputBufferProvider);
-    Result setParameterImpl(
-            uint32_t paramSize, const void* paramData, uint32_t valueSize, const void* valueData);
 };
 
 }  // namespace implementation
diff --git a/audio/effect/2.0/default/EffectsFactory.cpp b/audio/effect/2.0/default/EffectsFactory.cpp
index 572a428..08d92bd 100644
--- a/audio/effect/2.0/default/EffectsFactory.cpp
+++ b/audio/effect/2.0/default/EffectsFactory.cpp
@@ -95,7 +95,7 @@
     status = EffectQueryNumberEffects(&numEffects);
     if (status != OK) {
         retval = Result::NOT_INITIALIZED;
-        ALOGW("Error querying number of effects: %s", strerror(-status));
+        ALOGE("Error querying number of effects: %s", strerror(-status));
         goto exit;
     }
     result.resize(numEffects);
@@ -105,7 +105,7 @@
         if (status == OK) {
             effectDescriptorFromHal(halDescriptor, &result[i]);
         } else {
-            ALOGW("Error querying effect at position %d / %d: %s",
+            ALOGE("Error querying effect at position %d / %d: %s",
                     i, numEffects, strerror(-status));
             switch (status) {
                 case -ENOSYS: {
@@ -139,7 +139,7 @@
     effectDescriptorFromHal(halDescriptor, &descriptor);
     Result retval(Result::OK);
     if (status != OK) {
-        ALOGW("Error querying effect descriptor for %s: %s",
+        ALOGE("Error querying effect descriptor for %s: %s",
                 uuidToString(halUuid).c_str(), strerror(-status));
         if (status == -ENOENT) {
             retval = Result::INVALID_ARGUMENTS;
@@ -168,11 +168,13 @@
             effect = dispatchEffectInstanceCreation(halDescriptor, handle);
             effectId = EffectMap::getInstance().add(handle);
         } else {
+            ALOGE("Error querying effect descriptor for %s: %s",
+                    uuidToString(halUuid).c_str(), strerror(-status));
             EffectRelease(handle);
         }
     }
     if (status != OK) {
-        ALOGW("Error creating effect %s: %s", uuidToString(halUuid).c_str(), strerror(-status));
+        ALOGE("Error creating effect %s: %s", uuidToString(halUuid).c_str(), strerror(-status));
         if (status == -ENOENT) {
             retval = Result::INVALID_ARGUMENTS;
         } else {
diff --git a/audio/effect/2.0/default/EqualizerEffect.cpp b/audio/effect/2.0/default/EqualizerEffect.cpp
index 223716c..808d8eb 100644
--- a/audio/effect/2.0/default/EqualizerEffect.cpp
+++ b/audio/effect/2.0/default/EqualizerEffect.cpp
@@ -35,10 +35,15 @@
 EqualizerEffect::~EqualizerEffect() {}
 
 void EqualizerEffect::propertiesFromHal(
-        t_equalizer_settings& halProperties,
+        const t_equalizer_settings& halProperties,
         IEqualizerEffect::AllProperties* properties) {
     properties->curPreset = halProperties.curPreset;
-    properties->bandLevels.setToExternal(&halProperties.bandLevels[0], halProperties.numBands);
+    // t_equalizer_settings incorrectly defines bandLevels as uint16_t,
+    // whereas the actual type of values used by effects is int16_t.
+    const int16_t* signedBandLevels =
+            reinterpret_cast<const int16_t*>(&halProperties.bandLevels[0]);
+    properties->bandLevels.setToExternal(
+            const_cast<int16_t*>(signedBandLevels), halProperties.numBands);
 }
 
 std::vector<uint8_t> EqualizerEffect::propertiesToHal(
@@ -200,18 +205,18 @@
 }
 
 Return<void> EqualizerEffect::getLevelRange(getLevelRange_cb _hidl_cb)  {
-    uint16_t halLevels[2] = { 0, 0 };
+    int16_t halLevels[2] = { 0, 0 };
     Result retval = mEffect->getParam(EQ_PARAM_LEVEL_RANGE, halLevels);
     _hidl_cb(retval, halLevels[0], halLevels[1]);
     return Void();
 }
 
-Return<Result> EqualizerEffect::setBandLevel(uint16_t band, uint16_t level)  {
+Return<Result> EqualizerEffect::setBandLevel(uint16_t band, int16_t level)  {
     return mEffect->setParam(EQ_PARAM_BAND_LEVEL, band, level);
 }
 
 Return<void> EqualizerEffect::getBandLevel(uint16_t band, getBandLevel_cb _hidl_cb)  {
-    uint16_t halLevel = 0;
+    int16_t halLevel = 0;
     Result retval = mEffect->getParam(EQ_PARAM_BAND_LEVEL, band, halLevel);
     _hidl_cb(retval, halLevel);
     return Void();
@@ -272,14 +277,28 @@
         const IEqualizerEffect::AllProperties& properties)  {
     t_equalizer_settings *halPropertiesPtr = nullptr;
     std::vector<uint8_t> halBuffer = propertiesToHal(properties, &halPropertiesPtr);
-    return mEffect->setParam(EQ_PARAM_PROPERTIES, *halPropertiesPtr);
+    uint32_t paramId = EQ_PARAM_PROPERTIES;
+    return mEffect->setParameterImpl(
+            sizeof(paramId), &paramId, halBuffer.size(), halPropertiesPtr);
 }
 
 Return<void> EqualizerEffect::getAllProperties(getAllProperties_cb _hidl_cb)  {
-    t_equalizer_settings halProperties;
-    Result retval = mEffect->getParam(EQ_PARAM_PROPERTIES, halProperties);
+    uint16_t numBands = 0;
+    Result retval = mEffect->getParam(EQ_PARAM_NUM_BANDS, numBands);
     AllProperties properties;
-    propertiesFromHal(halProperties, &properties);
+    if (retval != Result::OK) {
+        _hidl_cb(retval, properties);
+        return Void();
+    }
+    size_t valueSize = sizeof(t_equalizer_settings) + sizeof(int16_t) * numBands;
+    uint32_t paramId = EQ_PARAM_PROPERTIES;
+    retval = mEffect->getParameterImpl(
+            sizeof(paramId), &paramId, valueSize,
+            [&] (uint32_t, const void* valueData) {
+                const t_equalizer_settings* halProperties =
+                        reinterpret_cast<const t_equalizer_settings*>(valueData);
+                propertiesFromHal(*halProperties, &properties);
+            });
     _hidl_cb(retval, properties);
     return Void();
 }
diff --git a/audio/effect/2.0/default/EqualizerEffect.h b/audio/effect/2.0/default/EqualizerEffect.h
index c9bed4f..9e8d75b 100644
--- a/audio/effect/2.0/default/EqualizerEffect.h
+++ b/audio/effect/2.0/default/EqualizerEffect.h
@@ -114,7 +114,7 @@
     // Methods from ::android::hardware::audio::effect::V2_0::IEqualizerEffect follow.
     Return<void> getNumBands(getNumBands_cb _hidl_cb)  override;
     Return<void> getLevelRange(getLevelRange_cb _hidl_cb)  override;
-    Return<Result> setBandLevel(uint16_t band, uint16_t level)  override;
+    Return<Result> setBandLevel(uint16_t band, int16_t level)  override;
     Return<void> getBandLevel(uint16_t band, getBandLevel_cb _hidl_cb)  override;
     Return<void> getBandCenterFrequency(
             uint16_t band, getBandCenterFrequency_cb _hidl_cb)  override;
@@ -132,7 +132,7 @@
     virtual ~EqualizerEffect();
 
     void propertiesFromHal(
-            t_equalizer_settings& halProperties,
+            const t_equalizer_settings& halProperties,
             IEqualizerEffect::AllProperties* properties);
     std::vector<uint8_t> propertiesToHal(
             const IEqualizerEffect::AllProperties& properties,
diff --git a/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp b/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp
index e58b42c..fda5eb0 100644
--- a/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp
+++ b/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp
@@ -182,7 +182,18 @@
 }
 
 Return<void> LoudnessEnhancerEffect::getTargetGain(getTargetGain_cb _hidl_cb)  {
-    return mEffect->getIntegerParam(LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB, _hidl_cb);
+    // AOSP Loudness Enhancer expects the size of the request to not include the
+    // size of the parameter.
+    uint32_t paramId = LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB;
+    uint32_t targetGainMb = 0;
+    Result retval = mEffect->getParameterImpl(
+            sizeof(paramId), &paramId,
+            0, sizeof(targetGainMb),
+            [&] (uint32_t, const void* valueData) {
+                memcpy(&targetGainMb, valueData, sizeof(targetGainMb));
+            });
+    _hidl_cb(retval, targetGainMb);
+    return Void();
 }
 
 } // namespace implementation
diff --git a/audio/effect/2.0/vts/functional/Android.bp b/audio/effect/2.0/vts/functional/Android.bp
index 1bc3f39..8a370cd 100644
--- a/audio/effect/2.0/vts/functional/Android.bp
+++ b/audio/effect/2.0/vts/functional/Android.bp
@@ -26,7 +26,10 @@
         "libhidltransport",
         "libnativehelper",
         "libutils",
+        "android.hardware.audio.common@2.0",
         "android.hardware.audio.effect@2.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
     ],
     static_libs: ["VtsHalHidlTargetTestBase"],
     cflags: [
diff --git a/audio/effect/2.0/vts/functional/VtsHalAudioEffectV2_0TargetTest.cpp b/audio/effect/2.0/vts/functional/VtsHalAudioEffectV2_0TargetTest.cpp
index 063243b..f6da213 100644
--- a/audio/effect/2.0/vts/functional/VtsHalAudioEffectV2_0TargetTest.cpp
+++ b/audio/effect/2.0/vts/functional/VtsHalAudioEffectV2_0TargetTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,47 +16,67 @@
 
 #define LOG_TAG "AudioEffectHidlHalTest"
 #include <android-base/logging.h>
-#include <cutils/native_handle.h>
+#include <system/audio.h>
 
+#include <android/hardware/audio/effect/2.0/IEffect.h>
 #include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
+#include <android/hardware/audio/effect/2.0/IEqualizerEffect.h>
+#include <android/hardware/audio/effect/2.0/ILoudnessEnhancerEffect.h>
 #include <android/hardware/audio/effect/2.0/types.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 
-using ::android::hardware::audio::common::V2_0::Uuid;
-using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
-using ::android::hardware::audio::effect::V2_0::IEffect;
-using ::android::hardware::audio::effect::V2_0::IEffectsFactory;
-using ::android::hardware::audio::effect::V2_0::Result;
-using ::android::hardware::Return;
-using ::android::hardware::Status;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_vec;
-using ::android::sp;
+using android::hardware::audio::common::V2_0::AudioDevice;
+using android::hardware::audio::common::V2_0::AudioHandleConsts;
+using android::hardware::audio::common::V2_0::AudioMode;
+using android::hardware::audio::common::V2_0::Uuid;
+using android::hardware::audio::effect::V2_0::AudioBuffer;
+using android::hardware::audio::effect::V2_0::EffectBufferConfig;
+using android::hardware::audio::effect::V2_0::EffectConfig;
+using android::hardware::audio::effect::V2_0::EffectDescriptor;
+using android::hardware::audio::effect::V2_0::EffectOffloadParameter;
+using android::hardware::audio::effect::V2_0::IEffect;
+using android::hardware::audio::effect::V2_0::IEffectsFactory;
+using android::hardware::audio::effect::V2_0::IEqualizerEffect;
+using android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect;
+using android::hardware::audio::effect::V2_0::Result;
+using android::hardware::MQDescriptorSync;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::hidl_memory;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hidl::allocator::V1_0::IAllocator;
+using android::hidl::memory::V1_0::IMemory;
+using android::sp;
 
-// The main test class for Audio Effect HIDL HAL.
-class AudioEffectHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+#endif
+
+// The main test class for Audio Effects Factory HIDL HAL.
+class AudioEffectsFactoryHidlTest : public ::testing::VtsHalHidlTargetTestBase {
  public:
-  virtual void SetUp() override {
-    effectsFactory = ::testing::VtsHalHidlTargetTestBase::getService<IEffectsFactory>();
+  void SetUp() override {
+    effectsFactory =
+        ::testing::VtsHalHidlTargetTestBase::getService<IEffectsFactory>();
     ASSERT_NE(effectsFactory, nullptr);
   }
 
-  virtual void TearDown() override {}
+  void TearDown() override { effectsFactory.clear(); }
+
+ protected:
+  static void description(const std::string& description) {
+    RecordProperty("description", description);
+  }
 
   sp<IEffectsFactory> effectsFactory;
 };
 
-// A class for test environment setup (kept since this file is a template).
-class AudioEffectHidlEnvironment : public ::testing::Environment {
- public:
-  virtual void SetUp() {}
-  virtual void TearDown() {}
-
- private:
-};
-
-TEST_F(AudioEffectHidlTest, EnumerateEffects) {
+TEST_F(AudioEffectsFactoryHidlTest, EnumerateEffects) {
+  description("Verify that EnumerateEffects returns at least one effect");
   Result retval = Result::NOT_INITIALIZED;
   size_t effectCount = 0;
   Return<void> ret = effectsFactory->getAllDescriptors(
@@ -65,11 +85,12 @@
         effectCount = result.size();
       });
   EXPECT_TRUE(ret.isOk());
-  EXPECT_EQ(retval, Result::OK);
+  EXPECT_EQ(Result::OK, retval);
   EXPECT_GT(effectCount, 0u);
 }
 
-TEST_F(AudioEffectHidlTest, CreateEffect) {
+TEST_F(AudioEffectsFactoryHidlTest, CreateEffect) {
+  description("Verify that an effect can be created via CreateEffect");
   bool gotEffect = false;
   Uuid effectUuid;
   Return<void> ret = effectsFactory->getAllDescriptors(
@@ -84,7 +105,7 @@
   Result retval = Result::NOT_INITIALIZED;
   sp<IEffect> effect;
   ret = effectsFactory->createEffect(
-      effectUuid, 1 /* session */, 1 /* ioHandle */,
+      effectUuid, 1 /*session*/, 1 /*ioHandle*/,
       [&](Result r, const sp<IEffect>& result, uint64_t /*effectId*/) {
         retval = r;
         if (r == Result::OK) {
@@ -92,11 +113,14 @@
         }
       });
   EXPECT_TRUE(ret.isOk());
-  EXPECT_EQ(retval, Result::OK);
-  EXPECT_NE(effect, nullptr);
+  EXPECT_EQ(Result::OK, retval);
+  EXPECT_NE(nullptr, effect.get());
 }
 
-TEST_F(AudioEffectHidlTest, GetDescriptor) {
+TEST_F(AudioEffectsFactoryHidlTest, GetDescriptor) {
+  description(
+      "Verify that effects factory can provide an effect descriptor via "
+      "GetDescriptor");
   hidl_vec<EffectDescriptor> allDescriptors;
   Return<void> ret = effectsFactory->getAllDescriptors(
       [&](Result r, const hidl_vec<EffectDescriptor>& result) {
@@ -116,10 +140,602 @@
   EXPECT_TRUE(ret.isOk());
 }
 
-int main(int argc, char** argv) {
-  ::testing::AddGlobalTestEnvironment(new AudioEffectHidlEnvironment);
-  ::testing::InitGoogleTest(&argc, argv);
-  int status = RUN_ALL_TESTS();
-  LOG(INFO) << "Test result = " << status;
-  return status;
+// Equalizer effect is required by CDD, but only the type is fixed.
+// This is the same UUID as AudioEffect.EFFECT_TYPE_EQUALIZER in Java.
+static const Uuid EQUALIZER_EFFECT_TYPE = {
+    0x0bed4300, 0xddd6, 0x11db, 0x8f34,
+    std::array<uint8_t, 6>{{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}};
+// Loudness Enhancer effect is required by CDD, but only the type is fixed.
+// This is the same UUID as AudioEffect.EFFECT_TYPE_LOUDNESS_ENHANCER in Java.
+static const Uuid LOUDNESS_ENHANCER_EFFECT_TYPE = {
+    0xfe3199be, 0xaed0, 0x413f, 0x87bb,
+    std::array<uint8_t, 6>{{0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}}};
+
+// The main test class for Audio Effect HIDL HAL.
+class AudioEffectHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+  void SetUp() override {
+    effectsFactory =
+        ::testing::VtsHalHidlTargetTestBase::getService<IEffectsFactory>();
+    ASSERT_NE(nullptr, effectsFactory.get());
+
+    findAndCreateEffect(getEffectType());
+    ASSERT_NE(nullptr, effect.get());
+
+    Return<Result> ret = effect->init();
+    ASSERT_TRUE(ret.isOk());
+    ASSERT_EQ(Result::OK, ret);
+  }
+
+  void TearDown() override {
+    effect.clear();
+    effectsFactory.clear();
+  }
+
+ protected:
+  static void description(const std::string& description) {
+    RecordProperty("description", description);
+  }
+
+  virtual Uuid getEffectType() { return EQUALIZER_EFFECT_TYPE; }
+
+  void findAndCreateEffect(const Uuid& type);
+  void findEffectInstance(const Uuid& type, Uuid* uuid);
+  void getChannelCount(uint32_t* channelCount);
+
+  sp<IEffectsFactory> effectsFactory;
+  sp<IEffect> effect;
+};
+
+void AudioEffectHidlTest::findAndCreateEffect(const Uuid& type) {
+  Uuid effectUuid;
+  findEffectInstance(type, &effectUuid);
+  Return<void> ret = effectsFactory->createEffect(
+      effectUuid, 1 /*session*/, 1 /*ioHandle*/,
+      [&](Result r, const sp<IEffect>& result, uint64_t /*effectId*/) {
+        if (r == Result::OK) {
+          effect = result;
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+}
+
+void AudioEffectHidlTest::findEffectInstance(const Uuid& type, Uuid* uuid) {
+  bool effectFound = false;
+  Return<void> ret = effectsFactory->getAllDescriptors(
+      [&](Result r, const hidl_vec<EffectDescriptor>& result) {
+        if (r == Result::OK) {
+          for (const auto& desc : result) {
+            if (desc.type == type) {
+              effectFound = true;
+              *uuid = desc.uuid;
+              break;
+            }
+          }
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_TRUE(effectFound);
+}
+
+void AudioEffectHidlTest::getChannelCount(uint32_t* channelCount) {
+  Result retval;
+  EffectConfig currentConfig;
+  Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+    retval = r;
+    if (r == Result::OK) {
+      currentConfig = conf;
+    }
+  });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+  ASSERT_TRUE(audio_channel_mask_is_valid(
+      static_cast<audio_channel_mask_t>(currentConfig.outputCfg.channels)));
+  *channelCount = audio_channel_count_from_out_mask(
+      static_cast<audio_channel_mask_t>(currentConfig.outputCfg.channels));
+}
+
+TEST_F(AudioEffectHidlTest, Close) {
+  description("Verify that an effect can be closed");
+  Return<Result> ret = effect->close();
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+}
+
+TEST_F(AudioEffectHidlTest, GetDescriptor) {
+  description(
+      "Verify that an effect can return its own descriptor via GetDescriptor");
+  Result retval = Result::NOT_INITIALIZED;
+  Uuid actualType;
+  Return<void> ret =
+      effect->getDescriptor([&](Result r, const EffectDescriptor& desc) {
+        retval = r;
+        if (r == Result::OK) {
+          actualType = desc.type;
+        }
+      });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, retval);
+  EXPECT_EQ(getEffectType(), actualType);
+}
+
+TEST_F(AudioEffectHidlTest, GetSetConfig) {
+  description(
+      "Verify that it is possible to manipulate effect config via Get / "
+      "SetConfig");
+  Result retval = Result::NOT_INITIALIZED;
+  EffectConfig currentConfig;
+  Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+    retval = r;
+    if (r == Result::OK) {
+      currentConfig = conf;
+    }
+  });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, retval);
+  Return<Result> ret2 = effect->setConfig(currentConfig, nullptr, nullptr);
+  EXPECT_TRUE(ret2.isOk());
+  EXPECT_EQ(Result::OK, ret2);
+}
+
+// Not generated automatically because AudioBuffer contains
+// instances of hidl_memory which can't be compared properly
+// in general case due to presence of handles.
+//
+// However, in this particular case, handles must not present
+// thus comparison is possible.
+//
+// operator== must be defined in the same namespace as the structures.
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+inline bool operator==(const AudioBuffer& lhs, const AudioBuffer& rhs) {
+  return lhs.id == rhs.id && lhs.frameCount == rhs.frameCount &&
+         lhs.data.handle() == nullptr && rhs.data.handle() == nullptr;
+}
+
+inline bool operator==(const EffectBufferConfig& lhs,
+                       const EffectBufferConfig& rhs) {
+  return lhs.buffer == rhs.buffer && lhs.samplingRateHz == rhs.samplingRateHz &&
+         lhs.channels == rhs.channels && lhs.format == rhs.format &&
+         lhs.accessMode == rhs.accessMode && lhs.mask == rhs.mask;
+}
+
+inline bool operator==(const EffectConfig& lhs, const EffectConfig& rhs) {
+  return lhs.inputCfg == rhs.inputCfg && lhs.outputCfg == rhs.outputCfg;
+}
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+TEST_F(AudioEffectHidlTest, Reset) {
+  description("Verify that Reset preserves effect configuration");
+  Result retval = Result::NOT_INITIALIZED;
+  EffectConfig originalConfig;
+  Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+    retval = r;
+    if (r == Result::OK) {
+      originalConfig = conf;
+    }
+  });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+  Return<Result> ret2 = effect->reset();
+  EXPECT_TRUE(ret2.isOk());
+  EXPECT_EQ(Result::OK, ret2);
+  EffectConfig configAfterReset;
+  ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+    retval = r;
+    if (r == Result::OK) {
+      configAfterReset = conf;
+    }
+  });
+  EXPECT_EQ(originalConfig, configAfterReset);
+}
+
+TEST_F(AudioEffectHidlTest, DisableEnableDisable) {
+  description("Verify Disable -> Enable -> Disable sequence for an effect");
+  Return<Result> ret = effect->disable();
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::INVALID_ARGUMENTS, ret);
+  ret = effect->enable();
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+  ret = effect->disable();
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+}
+
+TEST_F(AudioEffectHidlTest, SetDevice) {
+  description("Verify that SetDevice works for an output chain effect");
+  Return<Result> ret = effect->setDevice(AudioDevice::OUT_SPEAKER);
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+}
+
+TEST_F(AudioEffectHidlTest, SetAndGetVolume) {
+  description("Verify that SetAndGetVolume method works for an effect");
+  uint32_t channelCount;
+  getChannelCount(&channelCount);
+  hidl_vec<uint32_t> volumes;
+  volumes.resize(channelCount);
+  for (uint32_t i = 0; i < channelCount; ++i) {
+    volumes[i] = 0;
+  }
+  Result retval = Result::NOT_INITIALIZED;
+  Return<void> ret = effect->setAndGetVolume(
+      volumes, [&](Result r, const hidl_vec<uint32_t>&) { retval = r; });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, retval);
+}
+
+TEST_F(AudioEffectHidlTest, VolumeChangeNotification) {
+  description("Verify that effect accepts VolumeChangeNotification");
+  uint32_t channelCount;
+  getChannelCount(&channelCount);
+  hidl_vec<uint32_t> volumes;
+  volumes.resize(channelCount);
+  for (uint32_t i = 0; i < channelCount; ++i) {
+    volumes[i] = 0;
+  }
+  Return<Result> ret = effect->volumeChangeNotification(volumes);
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+}
+
+TEST_F(AudioEffectHidlTest, SetAudioMode) {
+  description("Verify that SetAudioMode works for an effect");
+  Return<Result> ret = effect->setAudioMode(AudioMode::NORMAL);
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+}
+
+TEST_F(AudioEffectHidlTest, Offload) {
+  description("Verify that calling Offload methods works for an effect");
+  EffectOffloadParameter offloadParam;
+  offloadParam.isOffload = false;
+  offloadParam.ioHandle =
+      static_cast<int>(AudioHandleConsts::AUDIO_IO_HANDLE_NONE);
+  Return<Result> ret = effect->offload(offloadParam);
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+}
+
+TEST_F(AudioEffectHidlTest, PrepareForProcessing) {
+  description("Verify that PrepareForProcessing method works for an effect");
+  Result retval = Result::NOT_INITIALIZED;
+  Return<void> ret = effect->prepareForProcessing(
+      [&](Result r, const MQDescriptorSync<Result>&) { retval = r; });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, retval);
+}
+
+TEST_F(AudioEffectHidlTest, SetProcessBuffers) {
+  description("Verify that SetProcessBuffers works for an effect");
+  sp<IAllocator> ashmem = IAllocator::getService("ashmem");
+  ASSERT_NE(nullptr, ashmem.get());
+  bool success = false;
+  AudioBuffer buffer;
+  Return<void> ret =
+      ashmem->allocate(1024, [&](bool s, const hidl_memory& memory) {
+        success = s;
+        if (s) {
+          buffer.data = memory;
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_TRUE(success);
+  Return<Result> ret2 = effect->setProcessBuffers(buffer, buffer);
+  EXPECT_TRUE(ret2.isOk());
+  EXPECT_EQ(Result::OK, ret2);
+}
+
+// Testing getConfigReverse, getAuxChannelsConfig,
+// getSupportedAuxChannelsConfigs, setAudioSource, setConfigReverse,
+// setInputDevice doesn't make sense, because normally they are not supported by
+// the Equalizer, but it wouldn't be a problem if some vendor implementation
+// supports them, thus we can't test these methods neither for success, nor for
+// failure.
+
+// command, getParameter, getSupportedConfigsForFeature,
+// getCurrentConfigForFeature, setCurrentConfigForFeature, setParameter are
+// opaque channels between vendor apps and HALs, and can't be meaningfully
+// tested with effects that don't support them.
+
+// The main test class for Equalizer Audio Effect HIDL HAL.
+class EqualizerAudioEffectHidlTest : public AudioEffectHidlTest {
+ public:
+  void SetUp() override {
+    AudioEffectHidlTest::SetUp();
+    equalizer = IEqualizerEffect::castFrom(effect);
+    ASSERT_NE(nullptr, equalizer.get());
+  }
+
+ protected:
+  Uuid getEffectType() override { return EQUALIZER_EFFECT_TYPE; }
+  void getNumBands(uint16_t* numBands);
+  void getLevelRange(int16_t* minLevel, int16_t* maxLevel);
+  void getBandFrequencyRange(uint16_t band, uint32_t* minFreq,
+                             uint32_t* centerFreq, uint32_t* maxFreq);
+  void getPresetCount(size_t* count);
+
+  sp<IEqualizerEffect> equalizer;
+};
+
+void EqualizerAudioEffectHidlTest::getNumBands(uint16_t* numBands) {
+  Result retval = Result::NOT_INITIALIZED;
+  Return<void> ret = equalizer->getNumBands([&](Result r, uint16_t b) {
+    retval = r;
+    if (retval == Result::OK) {
+      *numBands = b;
+    }
+  });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+}
+
+void EqualizerAudioEffectHidlTest::getLevelRange(int16_t* minLevel,
+                                                 int16_t* maxLevel) {
+  Result retval = Result::NOT_INITIALIZED;
+  Return<void> ret =
+      equalizer->getLevelRange([&](Result r, int16_t min, int16_t max) {
+        retval = r;
+        if (retval == Result::OK) {
+          *minLevel = min;
+          *maxLevel = max;
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+}
+
+void EqualizerAudioEffectHidlTest::getBandFrequencyRange(uint16_t band,
+                                                         uint32_t* minFreq,
+                                                         uint32_t* centerFreq,
+                                                         uint32_t* maxFreq) {
+  Result retval = Result::NOT_INITIALIZED;
+  Return<void> ret = equalizer->getBandFrequencyRange(
+      band, [&](Result r, uint32_t min, uint32_t max) {
+        retval = r;
+        if (retval == Result::OK) {
+          *minFreq = min;
+          *maxFreq = max;
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+  ret = equalizer->getBandCenterFrequency(band, [&](Result r, uint32_t center) {
+    retval = r;
+    if (retval == Result::OK) {
+      *centerFreq = center;
+    }
+  });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+}
+
+void EqualizerAudioEffectHidlTest::getPresetCount(size_t* count) {
+  Result retval = Result::NOT_INITIALIZED;
+  Return<void> ret = equalizer->getPresetNames(
+      [&](Result r, const hidl_vec<hidl_string>& names) {
+        retval = r;
+        if (retval == Result::OK) {
+          *count = names.size();
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Result::OK, retval);
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetNumBands) {
+  description("Verify that Equalizer effect reports at least one band");
+  uint16_t numBands = 0;
+  getNumBands(&numBands);
+  EXPECT_GT(numBands, 0);
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetLevelRange) {
+  description("Verify that Equalizer effect reports adequate band level range");
+  int16_t minLevel = 0x7fff, maxLevel = 0;
+  getLevelRange(&minLevel, &maxLevel);
+  EXPECT_GT(maxLevel, minLevel);
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetSetBandLevel) {
+  description(
+      "Verify that manipulating band levels works for Equalizer effect");
+  uint16_t numBands = 0;
+  getNumBands(&numBands);
+  ASSERT_GT(numBands, 0);
+  int16_t levels[3]{0x7fff, 0, 0};
+  getLevelRange(&levels[0], &levels[2]);
+  ASSERT_GT(levels[2], levels[0]);
+  levels[1] = (levels[2] + levels[0]) / 2;
+  for (uint16_t i = 0; i < numBands; ++i) {
+    for (size_t j = 0; j < ARRAY_SIZE(levels); ++j) {
+      Return<Result> ret = equalizer->setBandLevel(i, levels[j]);
+      EXPECT_TRUE(ret.isOk());
+      EXPECT_EQ(Result::OK, ret);
+      Result retval = Result::NOT_INITIALIZED;
+      int16_t actualLevel;
+      Return<void> ret2 = equalizer->getBandLevel(i, [&](Result r, int16_t l) {
+        retval = r;
+        if (retval == Result::OK) {
+          actualLevel = l;
+        }
+      });
+      EXPECT_TRUE(ret2.isOk());
+      EXPECT_EQ(Result::OK, retval);
+      EXPECT_EQ(levels[j], actualLevel);
+    }
+  }
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetBandCenterFrequencyAndRange) {
+  description(
+      "Verify that Equalizer effect reports adequate band frequency range");
+  uint16_t numBands = 0;
+  getNumBands(&numBands);
+  ASSERT_GT(numBands, 0);
+  for (uint16_t i = 0; i < numBands; ++i) {
+    uint32_t minFreq = 0xffffffff, centerFreq = 0xffffffff,
+             maxFreq = 0xffffffff;
+    getBandFrequencyRange(i, &minFreq, &centerFreq, &maxFreq);
+    // Note: NXP legacy implementation reports "1" as upper bound for last band,
+    // so this check fails.
+    EXPECT_GE(maxFreq, centerFreq);
+    EXPECT_GE(centerFreq, minFreq);
+  }
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetBandForFrequency) {
+  description(
+      "Verify that Equalizer effect supports GetBandForFrequency correctly");
+  uint16_t numBands = 0;
+  getNumBands(&numBands);
+  ASSERT_GT(numBands, 0);
+  for (uint16_t i = 0; i < numBands; ++i) {
+    uint32_t freqs[3]{0, 0, 0};
+    getBandFrequencyRange(i, &freqs[0], &freqs[1], &freqs[2]);
+    // NXP legacy implementation reports "1" as upper bound for last band, some
+    // of the checks fail.
+    for (size_t j = 0; j < ARRAY_SIZE(freqs); ++j) {
+      if (j == 0) {
+        freqs[j]++;
+      }  // Min frequency is an open interval.
+      Result retval = Result::NOT_INITIALIZED;
+      uint16_t actualBand = numBands + 1;
+      Return<void> ret =
+          equalizer->getBandForFrequency(freqs[j], [&](Result r, uint16_t b) {
+            retval = r;
+            if (retval == Result::OK) {
+              actualBand = b;
+            }
+          });
+      EXPECT_TRUE(ret.isOk());
+      EXPECT_EQ(Result::OK, retval);
+      EXPECT_EQ(i, actualBand) << "Frequency: " << freqs[j];
+    }
+  }
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetPresetNames) {
+  description("Verify that Equalizer effect reports at least one preset");
+  size_t presetCount;
+  getPresetCount(&presetCount);
+  EXPECT_GT(presetCount, 0u);
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetSetCurrentPreset) {
+  description(
+      "Verify that manipulating the current preset for Equalizer effect");
+  size_t presetCount;
+  getPresetCount(&presetCount);
+  ASSERT_GT(presetCount, 0u);
+  for (uint16_t i = 0; i < presetCount; ++i) {
+    Return<Result> ret = equalizer->setCurrentPreset(i);
+    EXPECT_TRUE(ret.isOk());
+    EXPECT_EQ(Result::OK, ret);
+    Result retval = Result::NOT_INITIALIZED;
+    uint16_t actualPreset = 0xffff;
+    Return<void> ret2 = equalizer->getCurrentPreset([&](Result r, uint16_t p) {
+      retval = r;
+      if (retval == Result::OK) {
+        actualPreset = p;
+      }
+    });
+    EXPECT_TRUE(ret2.isOk());
+    EXPECT_EQ(Result::OK, retval);
+    EXPECT_EQ(i, actualPreset);
+  }
+}
+
+TEST_F(EqualizerAudioEffectHidlTest, GetSetAllProperties) {
+  description(
+      "Verify that setting band levels and presets works via Get / "
+      "SetAllProperties for Equalizer effect");
+  using AllProperties =
+      android::hardware::audio::effect::V2_0::IEqualizerEffect::AllProperties;
+  uint16_t numBands = 0;
+  getNumBands(&numBands);
+  ASSERT_GT(numBands, 0);
+  AllProperties props;
+  props.bandLevels.resize(numBands);
+  for (size_t i = 0; i < numBands; ++i) {
+    props.bandLevels[i] = 0;
+  }
+
+  AllProperties actualProps;
+  Result retval = Result::NOT_INITIALIZED;
+
+  // Verify setting of the band levels via properties.
+  props.curPreset = -1;
+  Return<Result> ret = equalizer->setAllProperties(props);
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+  Return<void> ret2 =
+      equalizer->getAllProperties([&](Result r, AllProperties p) {
+        retval = r;
+        if (retval == Result::OK) {
+          actualProps = p;
+        }
+      });
+  EXPECT_TRUE(ret2.isOk());
+  EXPECT_EQ(Result::OK, retval);
+  EXPECT_EQ(props.bandLevels, actualProps.bandLevels);
+
+  // Verify setting of the current preset via properties.
+  props.curPreset = 0;  // Assuming there is at least one preset.
+  ret = equalizer->setAllProperties(props);
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+  ret2 = equalizer->getAllProperties([&](Result r, AllProperties p) {
+    retval = r;
+    if (retval == Result::OK) {
+      actualProps = p;
+    }
+  });
+  EXPECT_TRUE(ret2.isOk());
+  EXPECT_EQ(Result::OK, retval);
+  EXPECT_EQ(props.curPreset, actualProps.curPreset);
+}
+
+// The main test class for Equalizer Audio Effect HIDL HAL.
+class LoudnessEnhancerAudioEffectHidlTest : public AudioEffectHidlTest {
+ public:
+  void SetUp() override {
+    AudioEffectHidlTest::SetUp();
+    enhancer = ILoudnessEnhancerEffect::castFrom(effect);
+    ASSERT_NE(nullptr, enhancer.get());
+  }
+
+ protected:
+  Uuid getEffectType() override { return LOUDNESS_ENHANCER_EFFECT_TYPE; }
+
+  sp<ILoudnessEnhancerEffect> enhancer;
+};
+
+TEST_F(LoudnessEnhancerAudioEffectHidlTest, GetSetTargetGain) {
+  description(
+      "Verify that manipulating the target gain works for Loudness Enhancer "
+      "effect");
+  const int32_t gain = 100;
+  Return<Result> ret = enhancer->setTargetGain(gain);
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Result::OK, ret);
+  int32_t actualGain = 0;
+  Result retval;
+  Return<void> ret2 = enhancer->getTargetGain([&](Result r, int32_t g) {
+    retval = r;
+    if (retval == Result::OK) {
+      actualGain = g;
+    }
+  });
+  EXPECT_TRUE(ret2.isOk());
+  EXPECT_EQ(Result::OK, retval);
+  EXPECT_EQ(gain, actualGain);
 }