Merge "IRPC test: use version from RpcHardwareInfo"
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 4871058..40aa229 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -148,11 +148,19 @@
     name: "android.hardware.audio.effect",
     vendor_available: true,
     srcs: [
+        "android/hardware/audio/effect/Capability.aidl",
+        "android/hardware/audio/effect/CommandId.aidl",
         "android/hardware/audio/effect/Descriptor.aidl",
+        "android/hardware/audio/effect/Equalizer.aidl",
+        "android/hardware/audio/effect/Flags.aidl",
         "android/hardware/audio/effect/IEffect.aidl",
         "android/hardware/audio/effect/IFactory.aidl",
+        "android/hardware/audio/effect/Parameter.aidl",
+        "android/hardware/audio/effect/State.aidl",
     ],
     imports: [
+        "android.hardware.common-V2",
+        "android.hardware.common.fmq-V1",
         "android.hardware.audio.common-V1",
         "android.media.audio.common.types-V2",
     ],
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl
new file mode 100644
index 0000000..11acf5e
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union Capability {
+  android.hardware.audio.effect.Capability.VendorEffectCapability vendor;
+  android.hardware.audio.effect.Equalizer.Capability equalizer;
+  @VintfStability
+  parcelable VendorEffectCapability {
+    ParcelableHolder extension;
+  }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.aidl
new file mode 100644
index 0000000..79299ee
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@Backing(type="int") @VintfStability
+enum CommandId {
+  START = 0,
+  STOP = 1,
+  RESET = 2,
+  VENDOR_COMMAND_0 = 256,
+  VENDOR_COMMAND_1 = 257,
+  VENDOR_COMMAND_2 = 258,
+  VENDOR_COMMAND_3 = 259,
+  VENDOR_COMMAND_4 = 260,
+  VENDOR_COMMAND_5 = 261,
+  VENDOR_COMMAND_6 = 262,
+  VENDOR_COMMAND_7 = 263,
+  VENDOR_COMMAND_8 = 264,
+  VENDOR_COMMAND_9 = 265,
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
index 94cacd9..1c86cf3 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
@@ -35,6 +35,7 @@
 @VintfStability
 parcelable Descriptor {
   android.hardware.audio.effect.Descriptor.Common common;
+  android.hardware.audio.effect.Capability capability;
   const String EFFECT_TYPE_UUID_ENV_REVERB = "c2e5d5f0-94bd-4763-9cac-4e234d06839e";
   const String EFFECT_TYPE_UUID_PRESET_REVERB = "47382d60-ddd8-11db-bf3a-0002a5d5c51b";
   const String EFFECT_TYPE_UUID_EQUALIZER = "0bed4300-ddd6-11db-8f34-0002a5d5c51b";
@@ -56,5 +57,6 @@
   @VintfStability
   parcelable Common {
     android.hardware.audio.effect.Descriptor.Identity id;
+    android.hardware.audio.effect.Flags flags;
   }
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl
new file mode 100644
index 0000000..31732d3
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union Equalizer {
+  android.hardware.audio.effect.Equalizer.VendorExtension vendor;
+  @VintfStability
+  parcelable Capability {
+    ParcelableHolder extension;
+  }
+  @VintfStability
+  parcelable VendorExtension {
+    ParcelableHolder extension;
+  }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Flags.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Flags.aidl
new file mode 100644
index 0000000..af774e8
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Flags.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+parcelable Flags {
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl
index 7f868ad..e5c96f5 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl
@@ -34,7 +34,23 @@
 package android.hardware.audio.effect;
 @VintfStability
 interface IEffect {
-  void open();
+  android.hardware.audio.effect.IEffect.OpenEffectReturn open(in android.hardware.audio.effect.Parameter.Common common, in android.hardware.audio.effect.Parameter.Specific specific);
   void close();
   android.hardware.audio.effect.Descriptor getDescriptor();
+  void command(in android.hardware.audio.effect.CommandId commandId);
+  android.hardware.audio.effect.State getState();
+  void setParameter(in android.hardware.audio.effect.Parameter param);
+  android.hardware.audio.effect.Parameter getParameter(in android.hardware.audio.effect.Parameter.Id paramId);
+  @FixedSize @VintfStability
+  parcelable Status {
+    int status;
+    int fmqByteConsumed;
+    int fmqByteProduced;
+  }
+  @VintfStability
+  parcelable OpenEffectReturn {
+    android.hardware.common.fmq.MQDescriptor<android.hardware.audio.effect.IEffect.Status,android.hardware.common.fmq.SynchronizedReadWrite> statusMQ;
+    android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> inputDataMQ;
+    android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> outputDataMQ;
+  }
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl
new file mode 100644
index 0000000..16bd3bb
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union Parameter {
+  android.hardware.audio.effect.Parameter.Common common;
+  android.hardware.audio.effect.Parameter.VendorEffectParameter vendorEffect;
+  android.hardware.audio.effect.Parameter.Specific specific;
+  @VintfStability
+  union Id {
+    int commonTag;
+    int vendorTag;
+    android.hardware.audio.effect.Parameter.Specific.Tag specificTag;
+  }
+  @VintfStability
+  parcelable Common {
+    int session;
+    int ioHandle;
+    android.media.audio.common.AudioDeviceDescription device;
+    android.media.audio.common.AudioConfig input;
+    android.media.audio.common.AudioConfig output;
+  }
+  @VintfStability
+  parcelable VendorEffectParameter {
+    ParcelableHolder extension;
+  }
+  @VintfStability
+  union Specific {
+    android.hardware.audio.effect.Equalizer equalizer;
+  }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl
new file mode 100644
index 0000000..3176b01
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@Backing(type="byte") @VintfStability
+enum State {
+  INIT = 0,
+  IDLE = 1,
+  PROCESSING = 2,
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Capability.aidl b/audio/aidl/android/hardware/audio/effect/Capability.aidl
new file mode 100644
index 0000000..e792f86
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Capability.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect;
+
+import android.hardware.audio.effect.Equalizer;
+
+/**
+ * Effect capability definitions.
+ * This data structure is used as part of effect Descriptor to identify effect capabilities which
+ * not meant to change at runtime.
+ */
+@VintfStability
+union Capability {
+    /**
+     * Vendor defined effect capability.
+     * This extension can be used when vendor have a new effect implementated and need
+     * capability definition for this new type of effect.
+     * If vendor want to extend existing effect capabilities, it is recommended to expose though
+     * the ParcelableHolder in each effect capability definition. For example:
+     * Equalizer.Capability.extension.
+     */
+    @VintfStability
+    parcelable VendorEffectCapability {
+        ParcelableHolder extension;
+    }
+    VendorEffectCapability vendor;
+
+    /**
+     * Equalizer capability definition.
+     */
+    Equalizer.Capability equalizer;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/CommandId.aidl b/audio/aidl/android/hardware/audio/effect/CommandId.aidl
new file mode 100644
index 0000000..208c163
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/CommandId.aidl
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect;
+
+/**
+ * Defines all commands supported by the effect instance.
+ *
+ * There are three groups of commands:
+ * 1. Common part which MUST be supported by all effects.
+ * 2. Commands MUST be supported by a specific type of effect.
+ * 3. Extension commands for vendor.
+ */
+@VintfStability
+@Backing(type="int")
+enum CommandId {
+    /// MUST be supported by all effects
+    /**
+     * Start effect engine processing.
+     * An effect instance must start processing data and transfer to PROCESSING state if it is in
+     * IDLE state and have all necessary information. Otherwise it must:
+     * 1. Throw a EX_ILLEGAL_STATE exception if effect is not in IDLE state, or
+     * 2. Throw a EX_TRANSACTION_FAILED for all other errors.
+     *
+     * Depending on parameters set to the effect instance, effect may do process or reverse
+     * process after START command.
+     */
+    START = 0,
+    /**
+     * Stop effect engine processing with all resource kept.
+     * The currently processed audio data will be discarded if the effect engine is in PROCESSING
+     * state.
+     * Effect instance must do nothing and return ok when it receive STOP command in IDLE state.
+     */
+    STOP = 1,
+    /**
+     * Keep all parameter settings but reset the buffer content, stop engine processing, and transit
+     * instance state to IDLE if its in PROCESSING state.
+     * Effect instance must be able to handle RESET command at IDLE and PROCESSING states.
+     */
+    RESET = 2,
+
+    /// MUST be supported by a specific type of effect.
+    // Commands must supported by Equalizer.
+
+    /// Extension commands for vendor.
+    VENDOR_COMMAND_0 = 0x100,
+    VENDOR_COMMAND_1,
+    VENDOR_COMMAND_2,
+    VENDOR_COMMAND_3,
+    VENDOR_COMMAND_4,
+    VENDOR_COMMAND_5,
+    VENDOR_COMMAND_6,
+    VENDOR_COMMAND_7,
+    VENDOR_COMMAND_8,
+    VENDOR_COMMAND_9,
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
index 51b31c2..aca9bbe 100644
--- a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
@@ -16,12 +16,13 @@
 
 package android.hardware.audio.effect;
 
+import android.hardware.audio.effect.Capability;
+import android.hardware.audio.effect.Flags;
 import android.media.audio.common.AudioUuid;
 
 /**
- * Effect descriptor contains all information (capabilities, attributes, and ownership) for an
- * effect implemented in the Audio Effect HAL. Framework uses this information to decide when and
- * how to apply the effect.
+ * Descriptor contains all information (capabilities, attributes, etc) for an effect implementation.
+ * The client uses this information to decide when and how to apply an effect implementation.
  */
 @VintfStability
 parcelable Descriptor {
@@ -77,6 +78,15 @@
          * Identity of effect implementation.
          */
         Identity id;
+        /**
+         * Effect engine defined capabilities/requirements flags.
+         */
+        Flags flags;
     }
     Common common;
+
+    /**
+     * Effect implementation capability.
+     */
+    Capability capability;
 }
diff --git a/audio/aidl/android/hardware/audio/effect/Equalizer.aidl b/audio/aidl/android/hardware/audio/effect/Equalizer.aidl
new file mode 100644
index 0000000..309874d
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Equalizer.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect;
+
+import android.media.audio.common.AudioProfile;
+
+/**
+ * Equalizer specific definitions.
+ */
+@VintfStability
+union Equalizer {
+    /**
+     * Defines Equalizer implementation capabilities, it MUST be supported by all equalizer
+     * implementations.
+     *
+     * Equalizer.Capability definition is used by android.hardware.audio.effect.Capability.
+     */
+    @VintfStability
+    parcelable Capability {
+        /**
+         * Equalizer capability extension, vendor can use this extension in case existing capability
+         * definition not enough.
+         */
+        ParcelableHolder extension;
+    }
+
+    // Vendor Equalizer implementation definition for additional parameters.
+    @VintfStability
+    parcelable VendorExtension {
+        ParcelableHolder extension;
+    }
+    VendorExtension vendor;
+}
diff --git a/audio/aidl/default/include/visualizer-impl/Visualizer.h b/audio/aidl/android/hardware/audio/effect/Flags.aidl
similarity index 60%
rename from audio/aidl/default/include/visualizer-impl/Visualizer.h
rename to audio/aidl/android/hardware/audio/effect/Flags.aidl
index 4b82dd0..8add975 100644
--- a/audio/aidl/default/include/visualizer-impl/Visualizer.h
+++ b/audio/aidl/android/hardware/audio/effect/Flags.aidl
@@ -14,18 +14,13 @@
  * limitations under the License.
  */
 
-#pragma once
+package android.hardware.audio.effect;
 
-#include <cstdlib>
-
-namespace aidl::android::hardware::audio::effect {
-
-// Visualizer implementation UUID.
-static const ::aidl::android::media::audio::common::AudioUuid VisualizerUUID = {
-        static_cast<int32_t>(0x1d4033c0),
-        0x8557,
-        0x11df,
-        0x9f2d,
-        {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-
-}  // namespace aidl::android::hardware::audio::effect
\ No newline at end of file
+/**
+ * The common part of available capability/configuration for effects. For effect type specific
+ * capability, see @c android.hardware.audio.effect.Capability.
+ */
+@VintfStability
+parcelable Flags {
+    // TODO: add Effect engine defined capabilities/requirements flags.
+}
diff --git a/audio/aidl/android/hardware/audio/effect/IEffect.aidl b/audio/aidl/android/hardware/audio/effect/IEffect.aidl
index d7a9501..9ab8b02 100644
--- a/audio/aidl/android/hardware/audio/effect/IEffect.aidl
+++ b/audio/aidl/android/hardware/audio/effect/IEffect.aidl
@@ -16,24 +16,68 @@
 
 package android.hardware.audio.effect;
 
+import android.hardware.audio.effect.CommandId;
 import android.hardware.audio.effect.Descriptor;
+import android.hardware.audio.effect.Parameter;
+import android.hardware.audio.effect.State;
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
 
 /**
  * Effect interfaces definitions to configure and control the effect instance.
  */
 @VintfStability
 interface IEffect {
+    @VintfStability
+    @FixedSize
+    parcelable Status {
+        /**
+         * One of Binder STATUS_* statuses:
+         *  - STATUS_OK: the command has completed successfully;
+         *  - STATUS_BAD_VALUE: invalid value in the 'Command' structure;
+         *  - STATUS_INVALID_OPERATION: the mix port is not connected
+         *                              to any producer or consumer, thus
+         *                              positions can not be reported;
+         *  - STATUS_NOT_ENOUGH_DATA: a read or write error has
+         *                            occurred for the 'audio.fmq' queue;
+         *
+         */
+        int status;
+        /**
+         * The amount of bytes consumed by the effect instance.
+         */
+        int fmqByteConsumed;
+        /**
+         * The amount of bytes produced by the effect instance.
+         */
+        int fmqByteProduced;
+    }
+
+    // Return data structure of IEffect.open() interface.
+    @VintfStability
+    parcelable OpenEffectReturn {
+        // Message queue for effect processing status.
+        MQDescriptor<Status, SynchronizedReadWrite> statusMQ;
+        // Message queue for input data buffer.
+        MQDescriptor<byte, SynchronizedReadWrite> inputDataMQ;
+        // Message queue for output data buffer.
+        MQDescriptor<byte, SynchronizedReadWrite> outputDataMQ;
+    }
+
     /**
-     * Open an effect instance, effect should not start processing data before receive START
-     * command. All necessary information should be allocated and instance should transfer to IDLE
-     * state after open() call has been handled successfully.
-     * After open, the effect instance should be able to handle all IEffect interface calls.
+     * Open an effect instance, effect must not start processing data before receive
+     * CommandId::START command. All necessary information should be allocated and instance must
+     * transfer to State::IDLE state after open() call has been handled successfully. After open,
+     * the effect instance must be able to handle all IEffect interface calls.
      *
+     * @param common Parameters which MUST pass from client at open time.
+     *
+     * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported command.
      * @throws a EX_UNSUPPORTED_OPERATION if device capability/resource is not enough or system
      *         failure happens.
      * @note Open an already-opened effect instance should do nothing and should not throw an error.
      */
-    void open();
+    OpenEffectReturn open(in Parameter.Common common, in Parameter.Specific specific);
 
     /**
      * Called by the client to close the effect instance, processing thread should be destroyed and
@@ -45,7 +89,7 @@
      *
      * Effect instance close interface should always succeed unless:
      * 1. The effect instance is not in a proper state to be closed, for example it's still in
-     * processing state.
+     * State::PROCESSING state.
      * 2. There is system/hardware related failure when close.
      *
      * @throws EX_ILLEGAL_STATE if the effect instance is not in a proper state to be closed.
@@ -62,4 +106,53 @@
      * @return Descriptor The @c Descriptor of this effect instance.
      */
     Descriptor getDescriptor();
+
+    /**
+     * Send a command (defined in enum CommandId) to the effect instance, instance state can be
+     * changed as result of command handling.
+     *
+     * Must be available for the effect instance after it has been open().
+     *
+     * @param commandId ID of the command send to the effect instance.
+     *
+     * @throws EX_ILLEGAL_STATE if the effect instance is not in a proper state to handle the
+     * command.
+     * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported command.
+     */
+    void command(in CommandId commandId);
+
+    /**
+     * Get current state of the effect instance.
+     *
+     * Must be available for the effect instance at anytime and should always succeed.
+     *
+     * @return Current effect instance state.
+     */
+    State getState();
+
+    /**
+     * Set a parameter to the effect instance.
+     *
+     * Must be available for the effect instance after open().
+     *
+     * @param param Parameter data to set to the effect instance.
+     *
+     * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported parameter.
+     */
+    void setParameter(in Parameter param);
+
+    /**
+     * Get a parameter from the effect instance with parameter ID.
+     *
+     * This interface must return the current parameter of the effect instance, if no parameter
+     * has been set by client yet, the default value must be returned.
+     *
+     * Must be available for the effect instance after open().
+     *
+     * @param paramId The tag enum of parameter to get.
+     * @return Parameter The parameter to get from the effect instance.
+     *
+     * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported parameter tag.
+     */
+    Parameter getParameter(in Parameter.Id paramId);
 }
diff --git a/audio/aidl/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/android/hardware/audio/effect/Parameter.aidl
new file mode 100644
index 0000000..2951660
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Parameter.aidl
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect;
+
+import android.hardware.audio.effect.Equalizer;
+import android.media.audio.common.AudioConfig;
+import android.media.audio.common.AudioDeviceDescription;
+/**
+ * Defines all parameters supported by the effect instance.
+ *
+ * There are three groups of parameters:
+ * 1. Common parameters are essential parameters, MUST pass to effects at open() interface.
+ * 2. Parameters defined for a specific effect type.
+ * 3. Extension parameters for vendor.
+ *
+ * For all supported parameter, implementation MUST support both set and get.
+ */
+@VintfStability
+union Parameter {
+    /**
+     * Client can pass in Parameter.Id with the corresponding tag value in IEffect.getParameter()
+     * call to get android.hardware.audio.effect.Parameter.
+     *
+     * As an example, if a client want to get audio.hardware.audio.effect.Specific.Equalizer, the
+     * value of Id should be audio.hardware.audio.effect.Parameter.Specific.equalizer.
+     */
+    @VintfStability
+    union Id {
+        // Common parameter tag.
+        int commonTag;
+        // Vendor defined parameter tag.
+        int vendorTag;
+        // Specific effect parameter tag.
+        Specific.Tag specificTag;
+    }
+
+    /**
+     * Common parameters MUST be supported by all effect implementations.
+     */
+    @VintfStability
+    parcelable Common {
+        // Type of Audio device.
+        int session;
+        // I/O Handle.
+        int ioHandle;
+        // Type of Audio device.
+        AudioDeviceDescription device;
+        // Input config.
+        AudioConfig input;
+        // Output config.
+        AudioConfig output;
+    }
+    Common common;
+
+    /**
+     * Parameters for vendor extension effect implementation usage.
+     */
+    @VintfStability
+    parcelable VendorEffectParameter {
+        ParcelableHolder extension;
+    }
+    VendorEffectParameter vendorEffect;
+
+    /**
+     * Parameters MUST be supported by a Specific type of effect.
+     */
+    @VintfStability
+    union Specific {
+        Equalizer equalizer;
+        // TODO: add other effect definitions here
+    }
+    Specific specific;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/State.aidl b/audio/aidl/android/hardware/audio/effect/State.aidl
new file mode 100644
index 0000000..85a4afc
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/State.aidl
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect;
+
+/**
+ * Possible states of an effect instance.
+ * A typical effect instance will be in INIT state when it is created with IFactory.createEffect()
+ * interface, transfer to IDLE after open(), and to PROCESSING after
+ * IEffect.command(Command.Id.START) command. When an effect instance receive STOP or RESET command,
+ * it should transfer to IDLE state after handle the command successfully. Effect instance should
+ * consume minimal resource and transfer to INIT state after it was close().
+ *
+ * Refer to State.gv for detailed state diagram.
+ */
+@VintfStability
+@Backing(type="byte")
+enum State {
+
+    /**
+     * An effect instance is in INIT state by default after it was created with
+     * IFactory.createEffect(). When an effect instance is in INIT state, it should have instance
+     * context initialized, and ready to handle IEffect.setParameter(), IEffect.open() as well as
+     * all getter interfaces.
+     *
+     * In INIT state, effect instance must:
+     * 1. Not handle any IEffect.command() and return EX_ILLEGAL_STATE with any Command.Id.
+     * 2. Be able to handle all parameter setting with IEffect.setParameter().
+     * 3. Be able to handle all getter interface calls like IEffect.getParameter() and
+     * IEffect.getState().
+     * 4. Be able to handle IEffect.open() successfully after configuration.
+     *
+     * Client is expected to do necessary configuration with IEffect.setParameter(), get all
+     * resource ready with IEffect.open(), and make sure effect instance transfer to IDLE state
+     * before sending commands with IEffect.command() interface. Effect instance must transfer
+     * from INIT to IDLE state after handle IEffect.open() call successfully.
+     */
+    INIT,
+    /**
+     * An effect instance transfer to IDLE state after it was open successfully with IEffect.open()
+     * in INIT state, or after it was stop/reset with Command.Id.STOP/RESET in PROCESSING state.
+     *
+     * In IDLE state, effect instance must:
+     * 1. Be able to start effect processing engine with IEffect.command(Command.Id.START) call.
+     * 2. Be able to handle all parameter setting with IEffect.setParameter().
+     * 3. Be able to handle all getter interface calls like IEffect.getParameter() and
+     * IEffect.getState().
+     *
+     * The following state transfer can happen in IDLE state:
+     * 1. Transfer to PROCESSING if instance receive an START command and start processing data
+     * successfully.
+     * 2. Transfer to INIT if instance receive a close() call.
+     */
+    IDLE,
+    /**
+     * An effect instance is in PROCESSING state after it receive an START command and start
+     * processing data successfully. Effect instance will transfer from PROCESSING to IDLE state if
+     * it receive an STOP or RESET command and handle the command successfully.
+     *
+     * When an instance is in PROCESSING state, client should try not to close() it directly,
+     * instead client should try to stop processing data first with STOP command before close(). In
+     * the case of a close() call received when instance in PROCESSING state, it should try to stop
+     * processing and transfer to IDLE first before close().
+     *
+     * In PROCESSING state, effect instance must:
+     * 1. Return EX_ILLEGAL_STATE if it's not able to handle any parameter settings at runtime.
+     * 2. Be able to handle STOP and RESET for IEffect.command() interface, and return
+     * EX_ILLEGAL_STATE for all other commands.
+     * 3. Must be able to handle all get* interface calls like IEffect.getParameter() and
+     * IEffect.getState().
+     */
+    PROCESSING,
+}
diff --git a/audio/aidl/android/hardware/audio/effect/state.gv b/audio/aidl/android/hardware/audio/effect/state.gv
new file mode 100644
index 0000000..e19e6c7
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/state.gv
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// To render: "dot -Tpng state.gv -o state.png"
+digraph effect_state_machine {
+    node [shape=point style=filled fillcolor=black width=0.5] I;
+    node [shape=doublecircle] F;
+    node [shape=oval width=1];
+    node [fillcolor=lightgreen] INIT;
+    node [fillcolor=lightblue] IDLE;
+    node [fillcolor=lightyellow] PROCESSING;
+
+    I -> INIT [label="IFactory.createEffect" labelfontcolor="navy"];
+    INIT -> F [label="IFactory.destroyEffect"];
+    INIT -> IDLE [label="open()" labelfontcolor="lime"];
+    IDLE -> PROCESSING [label="command(START"];
+    PROCESSING -> IDLE [label="command(STOP)\ncommand(RESET)"];
+    IDLE -> INIT [label="close()"];
+
+    INIT -> INIT [label="getState\ngetDescriptor"];
+    IDLE -> IDLE [label="getXXX\nsetParameter\ncommand(RESET)"];
+    PROCESSING -> PROCESSING [label="getXXX\nsetParameter"];
+}
\ No newline at end of file
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 53ed908..c48777f 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -81,18 +81,23 @@
 cc_library_static {
     name: "libaudioeffectserviceexampleimpl",
     defaults: ["aidlaudioeffectservice_defaults"],
-    export_include_dirs: [
-        "include",
-        "include/equalizer-impl/",
-    ],
+    export_include_dirs: ["include"],
     srcs: [
         "EffectFactory.cpp",
     ],
+    header_libs: [
+        "libsystem_headers",
+    ],
     visibility: [
         ":__subpackages__",
     ],
 }
 
+filegroup {
+    name: "effectCommonFile",
+    srcs: ["EffectThread.cpp"],
+}
+
 cc_binary {
     name: "android.hardware.audio.effect.service-aidl.example",
     relative_install_path: "hw",
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
index a9848fd..4877956 100644
--- a/audio/aidl/default/EffectFactory.cpp
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -16,57 +16,156 @@
 
 #define LOG_TAG "AHAL_EffectFactory"
 #include <android-base/logging.h>
+#include <dlfcn.h>
 
+#include "effect-impl/EffectUUID.h"
 #include "effectFactory-impl/EffectFactory.h"
-#include "equalizer-impl/Equalizer.h"
-#include "visualizer-impl/Visualizer.h"
 
 using aidl::android::media::audio::common::AudioUuid;
 
 namespace aidl::android::hardware::audio::effect {
 
 Factory::Factory() {
-    // TODO: implement this with xml parser on audio_effect.xml, and filter with optional
-    // parameters.
+    std::function<void(void*)> dlClose = [](void* handle) -> void {
+        if (handle && dlclose(handle)) {
+            LOG(ERROR) << "dlclose failed " << dlerror();
+        }
+    };
+    // TODO: implement this with audio_effect.xml.
+    auto libHandle =
+            std::unique_ptr<void, decltype(dlClose)>{dlopen("libequalizer.so", RTLD_LAZY), dlClose};
+    if (!libHandle) {
+        LOG(ERROR) << __func__ << ": dlopen failed, err: " << dlerror();
+        return;
+    }
+
+    LOG(DEBUG) << __func__ << " dlopen uuid: " << EqualizerSwImplUUID.toString() << " handle "
+               << libHandle;
+    mEffectLibMap.insert({EqualizerSwImplUUID, std::make_pair(std::move(libHandle), nullptr)});
+
     Descriptor::Identity id;
     id.type = EqualizerTypeUUID;
     id.uuid = EqualizerSwImplUUID;
     mIdentityList.push_back(id);
 }
 
-ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type,
-                                         const std::optional<AudioUuid>& in_instance,
+Factory::~Factory() {
+    if (auto count = mEffectUuidMap.size()) {
+        LOG(ERROR) << __func__ << " remaining " << count
+                   << " effect instances not destroyed indicating resource leak!";
+        for (const auto& it : mEffectUuidMap) {
+            if (auto spEffect = it.first.lock()) {
+                LOG(ERROR) << __func__ << " erase remaining instance UUID " << it.second.toString();
+                destroyEffectImpl(spEffect);
+            }
+        }
+    }
+}
+
+ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type_uuid,
+                                         const std::optional<AudioUuid>& in_impl_uuid,
                                          std::vector<Descriptor::Identity>* _aidl_return) {
     std::copy_if(mIdentityList.begin(), mIdentityList.end(), std::back_inserter(*_aidl_return),
                  [&](auto& desc) {
-                     return (!in_type.has_value() || in_type.value() == desc.type) &&
-                            (!in_instance.has_value() || in_instance.value() == desc.uuid);
+                     return (!in_type_uuid.has_value() || in_type_uuid.value() == desc.type) &&
+                            (!in_impl_uuid.has_value() || in_impl_uuid.value() == desc.uuid);
                  });
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Factory::createEffect(
-        const AudioUuid& in_impl_uuid,
-        std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>* _aidl_return) {
+#define RETURN_IF_BINDER_EXCEPTION(functor)                                 \
+    {                                                                       \
+        binder_exception_t exception = functor;                             \
+        if (EX_NONE != exception) {                                         \
+            LOG(ERROR) << #functor << ":  failed with error " << exception; \
+            return ndk::ScopedAStatus::fromExceptionCode(exception);        \
+        }                                                                   \
+    }
+
+ndk::ScopedAStatus Factory::createEffect(const AudioUuid& in_impl_uuid,
+                                         std::shared_ptr<IEffect>* _aidl_return) {
     LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString();
     if (in_impl_uuid == EqualizerSwImplUUID) {
-        *_aidl_return = ndk::SharedRefBase::make<Equalizer>();
+        if (mEffectLibMap.count(in_impl_uuid)) {
+            auto& lib = mEffectLibMap[in_impl_uuid];
+            // didn't do dlsym yet
+            if (nullptr == lib.second) {
+                void* libHandle = lib.first.get();
+                struct effect_interface_s intf = {
+                        .createEffectFunc = (EffectCreateFunctor)dlsym(libHandle, "createEffect"),
+                        .destroyEffectFunc =
+                                (EffectDestroyFunctor)dlsym(libHandle, "destroyEffect")};
+                auto dlInterface = std::make_unique<struct effect_interface_s>(intf);
+                if (!dlInterface->createEffectFunc || !dlInterface->destroyEffectFunc) {
+                    LOG(ERROR) << __func__
+                               << ": create or destroy symbol not exist in library: " << libHandle
+                               << "!";
+                    return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+                }
+                lib.second = std::move(dlInterface);
+            }
+
+            auto& libInterface = lib.second;
+            std::shared_ptr<IEffect> effectSp;
+            RETURN_IF_BINDER_EXCEPTION(libInterface->createEffectFunc(&effectSp));
+            if (!effectSp) {
+                LOG(ERROR) << __func__ << ": library created null instance without return error!";
+                return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+            }
+            *_aidl_return = effectSp;
+            mEffectUuidMap[std::weak_ptr<IEffect>(effectSp)] = in_impl_uuid;
+            LOG(DEBUG) << __func__ << ": instance " << effectSp.get() << " created successfully";
+            return ndk::ScopedAStatus::ok();
+        } else {
+            LOG(ERROR) << __func__ << ": library doesn't exist";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
     } else {
-        LOG(ERROR) << __func__ << ": UUID "
-                   << " not supported";
+        LOG(ERROR) << __func__ << ": UUID not supported";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Factory::destroyEffect(
-        const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_handle) {
-    if (in_handle) {
-        // TODO: b/245393900 need check the instance state with IEffect.getState before destroy.
+ndk::ScopedAStatus Factory::destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle) {
+    std::weak_ptr<IEffect> wpHandle(in_handle);
+    // find UUID with key (std::weak_ptr<IEffect>)
+    if (auto uuidIt = mEffectUuidMap.find(wpHandle); uuidIt != mEffectUuidMap.end()) {
+        auto& uuid = uuidIt->second;
+        // find implementation library with UUID
+        if (auto libIt = mEffectLibMap.find(uuid); libIt != mEffectLibMap.end()) {
+            if (libIt->second.second->destroyEffectFunc) {
+                RETURN_IF_BINDER_EXCEPTION(libIt->second.second->destroyEffectFunc(in_handle));
+            }
+        } else {
+            LOG(ERROR) << __func__ << ": UUID " << uuid.toString() << " does not exist in libMap!";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+        mEffectUuidMap.erase(uuidIt);
         return ndk::ScopedAStatus::ok();
     } else {
+        LOG(ERROR) << __func__ << ": instance " << in_handle << " does not exist!";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
 }
 
+// go over the map and cleanup all expired weak_ptrs.
+void Factory::cleanupEffectMap() {
+    for (auto it = mEffectUuidMap.begin(); it != mEffectUuidMap.end();) {
+        if (nullptr == it->first.lock()) {
+            it = mEffectUuidMap.erase(it);
+        } else {
+            ++it;
+        }
+    }
+}
+
+ndk::ScopedAStatus Factory::destroyEffect(const std::shared_ptr<IEffect>& in_handle) {
+    LOG(DEBUG) << __func__ << ": instance " << in_handle.get();
+    ndk::ScopedAStatus status = destroyEffectImpl(in_handle);
+    // always do the cleanup
+    cleanupEffectMap();
+    return status;
+}
+
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/EffectThread.cpp b/audio/aidl/default/EffectThread.cpp
new file mode 100644
index 0000000..0ad9a14
--- /dev/null
+++ b/audio/aidl/default/EffectThread.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_EffectThread"
+#include <android-base/logging.h>
+#include <pthread.h>
+#include <sys/resource.h>
+
+#include "effect-impl/EffectThread.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+EffectThread::EffectThread() {
+    LOG(DEBUG) << __func__;
+}
+
+EffectThread::~EffectThread() {
+    destroy();
+    LOG(DEBUG) << __func__ << " done";
+};
+
+RetCode EffectThread::create(const std::string& name, const int priority) {
+    if (mThread.joinable()) {
+        LOG(WARNING) << __func__ << " thread already created, no-op";
+        return RetCode::SUCCESS;
+    }
+    mName = name;
+    mPriority = priority;
+    mThread = std::thread(&EffectThread::threadLoop, this);
+    LOG(DEBUG) << __func__ << " " << name << " priority " << mPriority << " done";
+    return RetCode::SUCCESS;
+}
+
+RetCode EffectThread::destroy() {
+    {
+        std::lock_guard lg(mMutex);
+        mStop = mExit = true;
+    }
+    mCv.notify_one();
+
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+    LOG(DEBUG) << __func__ << " done";
+    return RetCode::SUCCESS;
+}
+
+RetCode EffectThread::start() {
+    if (!mThread.joinable()) {
+        LOG(ERROR) << __func__ << " thread already destroyed";
+        return RetCode::ERROR;
+    }
+
+    {
+        std::lock_guard lg(mMutex);
+        if (!mStop) {
+            LOG(WARNING) << __func__ << " already start";
+            return RetCode::SUCCESS;
+        }
+        mStop = false;
+    }
+
+    mCv.notify_one();
+    LOG(DEBUG) << __func__ << " done";
+    return RetCode::SUCCESS;
+}
+
+RetCode EffectThread::stop() {
+    if (!mThread.joinable()) {
+        LOG(ERROR) << __func__ << " thread already destroyed";
+        return RetCode::ERROR;
+    }
+
+    {
+        std::lock_guard lg(mMutex);
+        if (mStop) {
+            LOG(WARNING) << __func__ << " already stop";
+            return RetCode::SUCCESS;
+        }
+        mStop = true;
+    }
+    LOG(DEBUG) << __func__ << " done";
+    return RetCode::SUCCESS;
+}
+
+void EffectThread::threadLoop() {
+    pthread_setname_np(pthread_self(), mName.substr(0, MAX_TASK_COMM_LEN - 1).c_str());
+    setpriority(PRIO_PROCESS, 0, mPriority);
+    while (true) {
+        bool needExit = false;
+        {
+            std::unique_lock l(mMutex);
+            mCv.wait(l, [&]() REQUIRES(mMutex) {
+                needExit = mExit;
+                return mExit || !mStop;
+            });
+        }
+        if (needExit) {
+            LOG(WARNING) << __func__ << " EXIT!";
+            return;
+        }
+        // process without lock
+        process();
+    }
+}
+
+std::string toString(RetCode& code) {
+    switch (code) {
+        case RetCode::SUCCESS:
+            return "SUCCESS";
+        case RetCode::ERROR:
+            return "ERROR";
+        default:
+            return "EnumError";
+    }
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/equalizer/Android.bp b/audio/aidl/default/equalizer/Android.bp
index b842149..9c11347 100644
--- a/audio/aidl/default/equalizer/Android.bp
+++ b/audio/aidl/default/equalizer/Android.bp
@@ -27,17 +27,28 @@
     name: "libequalizer",
     vendor: true,
     shared_libs: [
+        "libaudioaidlcommon",
         "libbase",
-        "libbinder_ndk",
-        "libstagefright_foundation",
+        "android.hardware.common-V2-ndk",
     ],
     defaults: [
+        "aidlaudioservice_defaults",
         "latest_android_media_audio_common_types_ndk_shared",
         "latest_android_hardware_audio_effect_ndk_shared",
     ],
-    include_dirs: ["hardware/interfaces/audio/aidl/default/include/equalizer-impl"],
+    include_dirs: [
+        "hardware/interfaces/audio/aidl/default/include",
+        "system/media/audio/include",
+    ],
     srcs: [
         "Equalizer.cpp",
+        ":effectCommonFile",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
     ],
     visibility: [
         "//hardware/interfaces/audio/aidl/default",
diff --git a/audio/aidl/default/equalizer/Equalizer.cpp b/audio/aidl/default/equalizer/Equalizer.cpp
index 8b157fa..2e4e538 100644
--- a/audio/aidl/default/equalizer/Equalizer.cpp
+++ b/audio/aidl/default/equalizer/Equalizer.cpp
@@ -14,27 +14,243 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "AHAL_Equalizer"
+#define LOG_TAG "AHAL_EqualizerSw"
+#include <Utils.h>
 #include <android-base/logging.h>
+#include <unordered_set>
 
-#include "Equalizer.h"
+#include "effect-impl/EffectUUID.h"
+#include "equalizer-impl/EqualizerSw.h"
+
+using android::hardware::audio::common::getFrameSizeInBytes;
 
 namespace aidl::android::hardware::audio::effect {
 
-ndk::ScopedAStatus Equalizer::open() {
+extern "C" binder_exception_t createEffect(std::shared_ptr<IEffect>* instanceSpp) {
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<EqualizerSw>();
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
+    State state;
+    ndk::ScopedAStatus status = instanceSp->getState(&state);
+    if (!status.isOk() || State::INIT != state) {
+        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+                   << " in state: " << toString(state) << ", status: " << status.getDescription();
+        return EX_ILLEGAL_STATE;
+    }
+    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+    return EX_NONE;
+}
+
+ndk::ScopedAStatus EqualizerSw::open(const Parameter::Common& common,
+                                     const Parameter::Specific& specific,
+                                     OpenEffectReturn* _aidl_return) {
+    LOG(DEBUG) << __func__;
+    if (mState != State::INIT) {
+        LOG(WARNING) << __func__ << " eq already open";
+        return ndk::ScopedAStatus::ok();
+    }
+
+    // Set essential parameters before create worker thread.
+    setCommonParameter(common);
+    setSpecificParameter(specific);
+
+    LOG(DEBUG) << " common: " << common.toString() << " specific " << specific.toString();
+
+    auto& input = common.input;
+    auto& output = common.output;
+    size_t inputFrameSize = getFrameSizeInBytes(input.base.format, input.base.channelMask);
+    size_t outputFrameSize = getFrameSizeInBytes(output.base.format, output.base.channelMask);
+    if (!createFmq(1, input.frameCount * inputFrameSize, output.frameCount * outputFrameSize,
+                   _aidl_return)) {
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION,
+                                                                "FailedToCreateFmq");
+    }
+
+    // create the worker thread
+    if (RetCode::SUCCESS != mWorker->create(LOG_TAG)) {
+        LOG(ERROR) << __func__ << " created worker thread failed";
+        destroyFmq();
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION,
+                                                                "FailedToCreateFmq");
+    }
+
+    mState = State::IDLE;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EqualizerSw::close() {
+    if (mState == State::INIT) {
+        LOG(WARNING) << __func__ << " instance already closed";
+        return ndk::ScopedAStatus::ok();
+    } else if (mState == State::PROCESSING) {
+        LOG(ERROR) << __func__ << " instance still processing";
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
+                                                                "EqInstanceProcessing");
+    }
+
+    // stop the worker thread
+    mState = State::INIT;
+    mWorker->destroy();
+    destroyFmq();
     LOG(DEBUG) << __func__;
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Equalizer::close() {
-    LOG(DEBUG) << __func__;
-    return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus Equalizer::getDescriptor(Descriptor* _aidl_return) {
-    LOG(DEBUG) << __func__ << "descriptor " << mDesc.toString();
+ndk::ScopedAStatus EqualizerSw::getDescriptor(Descriptor* _aidl_return) {
+    LOG(DEBUG) << __func__ << mDesc.toString();
     *_aidl_return = mDesc;
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus EqualizerSw::command(CommandId in_commandId) {
+    LOG(DEBUG) << __func__ << ": receive command:" << toString(in_commandId);
+    if (mState == State::INIT) {
+        LOG(ERROR) << __func__ << ": instance not open yet";
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
+                                                                "CommandStateError");
+    }
+    switch (in_commandId) {
+        case CommandId::START:
+            // start processing.
+            mState = State::PROCESSING;
+            mWorker->start();
+            LOG(DEBUG) << __func__ << " state: " << toString(mState);
+            return ndk::ScopedAStatus::ok();
+        case CommandId::STOP:
+            // stop processing.
+            mState = State::IDLE;
+            mWorker->stop();
+            LOG(DEBUG) << __func__ << " state: " << toString(mState);
+            return ndk::ScopedAStatus::ok();
+        case CommandId::RESET:
+            // TODO: reset buffer status.
+            mState = State::IDLE;
+            mWorker->stop();
+            LOG(DEBUG) << __func__ << " state: " << toString(mState);
+            return ndk::ScopedAStatus::ok();
+        default:
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "CommandIdNotSupported");
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EqualizerSw::setParameter(const Parameter& in_param) {
+    if (mState == State::INIT) {
+        LOG(ERROR) << __func__ << ": instance not open yet";
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE, "StateError");
+    }
+    LOG(DEBUG) << __func__ << " with: " << in_param.toString();
+    auto tag = in_param.getTag();
+    switch (tag) {
+        case Parameter::common: {
+            return setCommonParameter(in_param.get<Parameter::common>());
+        }
+        case Parameter::specific: {
+            return setSpecificParameter(in_param.get<Parameter::specific>());
+        }
+        default:
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "ParameterNotSupported");
+    }
+}
+
+ndk::ScopedAStatus EqualizerSw::getParameter(const Parameter::Id& in_paramId,
+                                             Parameter* _aidl_return) {
+    LOG(DEBUG) << __func__ << in_paramId.toString();
+    auto tag = in_paramId.getTag();
+    switch (tag) {
+        case Parameter::Id::commonTag: {
+            _aidl_return->set<Parameter::common>(mCommonParam);
+            LOG(DEBUG) << __func__ << " get: " << _aidl_return->toString();
+            return ndk::ScopedAStatus::ok();
+        }
+        case Parameter::Id::specificTag: {
+            auto& id = in_paramId.get<Parameter::Id::specificTag>();
+            if (id != Parameter::Specific::equalizer) {
+                LOG(ERROR) << " unsupported parameter Id: " << in_paramId.toString();
+                return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                        EX_ILLEGAL_ARGUMENT, "Parameter::IdNotSupported");
+            }
+            Parameter::Specific specific;
+            specific.set<Parameter::Specific::equalizer>(mEqualizerParam);
+            _aidl_return->set<Parameter::specific>(specific);
+            LOG(DEBUG) << __func__ << _aidl_return->toString();
+            return ndk::ScopedAStatus::ok();
+        }
+        default:
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "Parameter::IdNotSupported");
+    }
+}
+
+ndk::ScopedAStatus EqualizerSw::getState(State* _aidl_return) {
+    *_aidl_return = mState;
+    return ndk::ScopedAStatus::ok();
+}
+
+/// Private methods.
+bool EqualizerSw::createFmq(int statusDepth, int inBufferSize, int outBufferSize,
+                            OpenEffectReturn* ret) {
+    mStatusMQ = std::make_unique<StatusMQ>(statusDepth, true /*configureEventFlagWord*/);
+    mInputMQ = std::make_unique<DataMQ>(inBufferSize);
+    mOutputMQ = std::make_unique<DataMQ>(outBufferSize);
+
+    if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) {
+        LOG(ERROR) << __func__ << " created invalid FMQ";
+        return false;
+    }
+    ret->statusMQ = mStatusMQ->dupeDesc();
+    ret->inputDataMQ = mInputMQ->dupeDesc();
+    ret->outputDataMQ = mOutputMQ->dupeDesc();
+    return true;
+}
+
+void EqualizerSw::destroyFmq() {
+    mStatusMQ.reset(nullptr);
+    mInputMQ.reset(nullptr);
+    mOutputMQ.reset(nullptr);
+}
+
+ndk::ScopedAStatus EqualizerSw::setCommonParameter(const Parameter::Common& common) {
+    mCommonParam = common;
+    LOG(DEBUG) << __func__ << " set: " << mCommonParam.toString();
+    return ndk::ScopedAStatus::ok();
+}
+
+// TODO: implementation need change to save all parameters.
+ndk::ScopedAStatus EqualizerSw::setSpecificParameter(const Parameter::Specific& specific) {
+    if (Parameter::Specific::equalizer != specific.getTag()) {
+        LOG(ERROR) << " unsupported effect: " << specific.toString();
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                "EffectNotSupported");
+    }
+
+    mEqualizerParam = specific.get<Parameter::Specific::equalizer>();
+    LOG(DEBUG) << __func__ << mEqualizerParam.toString();
+    return ndk::ScopedAStatus::ok();
+}
+
+void EqualizerSw::cleanUp() {
+    if (State::PROCESSING == mState) {
+        command(CommandId::STOP);
+    }
+    if (State::INIT != mState) {
+        close();
+    }
+}
+
+// Processing method running in worker thread.
+void EqualizerSwWorker::process() {
+    // TODO: add EQ processing with FMQ, should wait until data available before data processing.
+}
+
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectThread.h b/audio/aidl/default/include/effect-impl/EffectThread.h
new file mode 100644
index 0000000..e831cea
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectThread.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <atomic>
+#include <string>
+#include <thread>
+
+#include <android-base/thread_annotations.h>
+#include <system/thread_defs.h>
+
+namespace aidl::android::hardware::audio::effect {
+
+enum class RetCode { SUCCESS, ERROR };
+
+std::string toString(RetCode& code);
+
+class EffectThread {
+  public:
+    // default priority is same as HIDL: ANDROID_PRIORITY_URGENT_AUDIO
+    EffectThread();
+    virtual ~EffectThread();
+
+    // called by effect implementation.
+    RetCode create(const std::string& name, const int priority = ANDROID_PRIORITY_URGENT_AUDIO);
+    RetCode destroy();
+    RetCode start();
+    RetCode stop();
+
+    // Will call process() in a loop if the thread is running.
+    void threadLoop();
+
+    // User of EffectThread must implement the effect processing logic in this method.
+    virtual void process() = 0;
+    const int MAX_TASK_COMM_LEN = 15;
+
+  private:
+    std::mutex mMutex;
+    std::condition_variable mCv;
+    bool mExit GUARDED_BY(mMutex) = false;
+    bool mStop GUARDED_BY(mMutex) = true;
+    std::thread mThread;
+    int mPriority;
+    std::string mName;
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h
new file mode 100644
index 0000000..99f6c24
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectUUID.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <aidl/android/media/audio/common/AudioUuid.h>
+
+namespace aidl::android::hardware::audio::effect {
+
+using ::aidl::android::media::audio::common::AudioUuid;
+
+// Equalizer type UUID.
+static const AudioUuid EqualizerTypeUUID = {static_cast<int32_t>(0x0bed4300),
+                                            0xddd6,
+                                            0x11db,
+                                            0x8f34,
+                                            {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+
+// Equalizer implementation UUID.
+static const AudioUuid EqualizerSwImplUUID = {static_cast<int32_t>(0x0bed4300),
+                                              0x847d,
+                                              0x11df,
+                                              0xbb17,
+                                              {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+
+// Visualizer type UUID.
+static const AudioUuid VisualizerTypeUUID = {static_cast<int32_t>(0x1d4033c0),
+                                             0x8557,
+                                             0x11df,
+                                             0x9f2d,
+                                             {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
index 8da5525..d373048 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <any>
+#include <map>
 #include <optional>
 #include <vector>
 
@@ -63,7 +65,26 @@
             override;
 
   private:
+    ~Factory();
     // List of effect descriptors supported by the devices.
     std::vector<Descriptor::Identity> mIdentityList;
+
+    typedef binder_exception_t (*EffectCreateFunctor)(std::shared_ptr<IEffect>*);
+    typedef binder_exception_t (*EffectDestroyFunctor)(const std::shared_ptr<IEffect>&);
+    struct effect_interface_s {
+        EffectCreateFunctor createEffectFunc;
+        EffectDestroyFunctor destroyEffectFunc;
+    };
+
+    std::map<aidl::android::media::audio::common::AudioUuid /* implementationUUID */,
+             std::pair<std::unique_ptr<void, std::function<void(void*)>> /* dlHandle */,
+                       std::unique_ptr<struct effect_interface_s>>>
+            mEffectLibMap;
+    std::map<std::weak_ptr<IEffect>, aidl::android::media::audio::common::AudioUuid,
+             std::owner_less<>>
+            mEffectUuidMap;
+
+    ndk::ScopedAStatus destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle);
+    void cleanupEffectMap();
 };
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/equalizer-impl/Equalizer.h b/audio/aidl/default/include/equalizer-impl/Equalizer.h
deleted file mode 100644
index ea16cb9..0000000
--- a/audio/aidl/default/include/equalizer-impl/Equalizer.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <aidl/android/hardware/audio/effect/BnEffect.h>
-#include <cstdlib>
-
-namespace aidl::android::hardware::audio::effect {
-
-// Equalizer type UUID.
-static const ::aidl::android::media::audio::common::AudioUuid EqualizerTypeUUID = {
-        static_cast<int32_t>(0x0bed4300),
-        0xddd6,
-        0x11db,
-        0x8f34,
-        {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-
-// Equalizer implementation UUID.
-static const ::aidl::android::media::audio::common::AudioUuid EqualizerSwImplUUID = {
-        static_cast<int32_t>(0x0bed4300),
-        0x847d,
-        0x11df,
-        0xbb17,
-        {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-
-class Equalizer : public BnEffect {
-  public:
-    Equalizer() = default;
-    ndk::ScopedAStatus open() override;
-    ndk::ScopedAStatus close() override;
-    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
-
-  private:
-    // Effect descriptor.
-    Descriptor mDesc = {.common = {.id = {.type = EqualizerTypeUUID, .uuid = EqualizerSwImplUUID}}};
-};
-}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/equalizer-impl/EqualizerSw.h b/audio/aidl/default/include/equalizer-impl/EqualizerSw.h
new file mode 100644
index 0000000..58ad1de
--- /dev/null
+++ b/audio/aidl/default/include/equalizer-impl/EqualizerSw.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectThread.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EqualizerSwWorker : public EffectThread {
+    // EqualizerSwWorker(const std::string name){EffectThread(name)};
+    void process() override;
+};
+
+class EqualizerSw : public BnEffect {
+  public:
+    EqualizerSw() {
+        // create the worker
+        mWorker = std::make_unique<EqualizerSwWorker>();
+        LOG(DEBUG) << __func__;
+    };
+    ~EqualizerSw() {
+        cleanUp();
+        LOG(DEBUG) << __func__;
+    };
+    ndk::ScopedAStatus open(const Parameter::Common& common, const Parameter::Specific& specific,
+                            OpenEffectReturn* _aidl_return) override;
+    ndk::ScopedAStatus close() override;
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+
+    ndk::ScopedAStatus getState(State* _aidl_return) override;
+    ndk::ScopedAStatus command(CommandId in_commandId) override;
+    ndk::ScopedAStatus setParameter(const Parameter& in_param) override;
+    ndk::ScopedAStatus getParameter(const Parameter::Id& in_paramId,
+                                    Parameter* _aidl_return) override;
+
+  private:
+    // effect processing thread.
+    std::unique_ptr<EqualizerSwWorker> mWorker;
+    // Effect descriptor.
+    const Descriptor mDesc = {
+            .common = {.id = {.type = EqualizerTypeUUID, .uuid = EqualizerSwImplUUID}}};
+
+    // Parameters.
+    Parameter::Common mCommonParam;
+    Equalizer mEqualizerParam;  // TODO: the equalizer parameter needs to update
+
+    // Instance state INIT by default.
+    State mState = State::INIT;
+
+    typedef ::android::AidlMessageQueue<
+            Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+            StatusMQ;
+    typedef ::android::AidlMessageQueue<
+            int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+            DataMQ;
+
+    std::unique_ptr<StatusMQ> mStatusMQ;
+    std::unique_ptr<DataMQ> mInputMQ;
+    std::unique_ptr<DataMQ> mOutputMQ;
+
+    ndk::ScopedAStatus setCommonParameter(const Parameter::Common& common_param);
+    ndk::ScopedAStatus setSpecificParameter(const Parameter::Specific& specific);
+    bool createFmq(int statusDepth, int inBufferSize, int outBufferSize, OpenEffectReturn* ret);
+    void destroyFmq();
+    void cleanUp();
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 6ea7cef..63fc415 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -43,6 +43,36 @@
 }
 
 cc_test {
+    name: "VtsHalAudioEffectFactoryTargetTest",
+    defaults: [
+        "latest_android_media_audio_common_types_ndk_static",
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsHalAudioEffectFactoryTargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.audio.effect-V1-ndk",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
+
+cc_test {
     name: "VtsHalAudioEffectTargetTest",
     defaults: [
         "latest_android_media_audio_common_types_ndk_static",
@@ -57,6 +87,8 @@
     ],
     static_libs: [
         "android.hardware.audio.effect-V1-ndk",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
     ],
     cflags: [
         "-Wall",
diff --git a/audio/aidl/vts/EffectFactoryHelper.h b/audio/aidl/vts/EffectFactoryHelper.h
new file mode 100644
index 0000000..3cbca45
--- /dev/null
+++ b/audio/aidl/vts/EffectFactoryHelper.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <android/binder_auto_utils.h>
+
+#include "TestUtils.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::Parameter;
+using aidl::android::media::audio::common::AudioUuid;
+
+class EffectFactoryHelper {
+  public:
+    explicit EffectFactoryHelper(const std::string& name) : mServiceName(name) {}
+
+    void ConnectToFactoryService() {
+        mEffectFactory = IFactory::fromBinder(binderUtil.connectToService(mServiceName));
+        ASSERT_NE(mEffectFactory, nullptr);
+    }
+
+    void RestartFactoryService() {
+        ASSERT_NE(mEffectFactory, nullptr);
+        mEffectFactory = IFactory::fromBinder(binderUtil.restartService());
+        ASSERT_NE(mEffectFactory, nullptr);
+        ClearEffectMap();
+    }
+
+    void QueryEffects(const std::optional<AudioUuid>& in_type,
+                      const std::optional<AudioUuid>& in_instance,
+                      std::vector<Descriptor::Identity>* _aidl_return) {
+        ASSERT_NE(mEffectFactory, nullptr);
+        EXPECT_IS_OK(mEffectFactory->queryEffects(in_type, in_instance, _aidl_return));
+        mIds = *_aidl_return;
+    }
+
+    void CreateEffects() {
+        ASSERT_NE(mEffectFactory, nullptr);
+        for (const auto& id : mIds) {
+            std::shared_ptr<IEffect> effect;
+            EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
+            EXPECT_NE(effect, nullptr) << id.toString();
+            if (effect) {
+                mEffectIdMap[effect] = id;
+            }
+        }
+    }
+
+    void CreateEffectsAndExpect(
+            const std::vector<std::pair<Descriptor::Identity, binder_exception_t>>& uuid_status) {
+        ASSERT_NE(mEffectFactory, nullptr);
+        for (const auto& it : uuid_status) {
+            std::shared_ptr<IEffect> effect;
+            auto status = mEffectFactory->createEffect(it.first.uuid, &effect);
+            EXPECT_STATUS(it.second, status);
+            if (effect) {
+                mEffectIdMap[effect] = it.first;
+            }
+        }
+    }
+
+    void DestroyEffectAndExpect(std::shared_ptr<IEffect>& instance, binder_exception_t exception) {
+        ASSERT_NE(mEffectFactory, nullptr);
+        auto status = mEffectFactory->destroyEffect(instance);
+        EXPECT_STATUS(exception, status);
+    }
+
+    void QueryAndCreateAllEffects() {
+        ASSERT_NE(mEffectFactory, nullptr);
+        EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, &mCompleteIds));
+        for (const auto& id : mCompleteIds) {
+            std::shared_ptr<IEffect> effect;
+            EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
+            EXPECT_NE(effect, nullptr) << id.toString();
+            mEffectIdMap[effect] = id;
+        }
+    }
+
+    void DestroyEffects(const binder_exception_t expected = EX_NONE, const int remaining = 0) {
+        ASSERT_NE(mEffectFactory, nullptr);
+
+        for (auto it = mEffectIdMap.begin(); it != mEffectIdMap.end();) {
+            auto erased = it++;
+            auto status = mEffectFactory->destroyEffect(erased->first);
+            EXPECT_STATUS(expected, status);
+            if (status.isOk()) {
+                mEffectIdMap.erase(erased);
+            }
+        }
+        EXPECT_EQ((unsigned int)remaining, mEffectIdMap.size());
+    }
+
+    std::shared_ptr<IFactory> GetFactory() { return mEffectFactory; }
+    const std::vector<Descriptor::Identity>& GetEffectIds() { return mIds; }
+    const std::vector<Descriptor::Identity>& GetCompleteEffectIdList() { return mCompleteIds; }
+    const std::map<std::shared_ptr<IEffect>, Descriptor::Identity>& GetEffectMap() {
+        return mEffectIdMap;
+    }
+    void ClearEffectMap() { mEffectIdMap.clear(); }
+
+  private:
+    std::shared_ptr<IFactory> mEffectFactory;
+    std::string mServiceName;
+    AudioHalBinderServiceUtil binderUtil;
+    std::vector<Descriptor::Identity> mIds;
+    std::vector<Descriptor::Identity> mCompleteIds;
+
+    std::map<std::shared_ptr<IEffect>, Descriptor::Identity> mEffectIdMap;
+};
diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
new file mode 100644
index 0000000..dd17a6f
--- /dev/null
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "VtsHalAudioEffectFactory"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+
+#include "AudioHalBinderServiceUtil.h"
+#include "EffectFactoryHelper.h"
+#include "TestUtils.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::media::audio::common::AudioUuid;
+
+/// Effect factory testing.
+class EffectFactoryTest : public testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(mFactory.ConnectToFactoryService()); }
+
+    void TearDown() override { mFactory.DestroyEffects(); }
+
+    EffectFactoryHelper mFactory = EffectFactoryHelper(GetParam());
+
+    // TODO: these UUID can get from config file
+    // ec7178ec-e5e1-4432-a3f4-4657e6795210
+    const AudioUuid nullUuid = {static_cast<int32_t>(0xec7178ec),
+                                0xe5e1,
+                                0x4432,
+                                0xa3f4,
+                                {0x46, 0x57, 0xe6, 0x79, 0x52, 0x10}};
+    const AudioUuid zeroUuid = {
+            static_cast<int32_t>(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
+    const Descriptor::Identity nullDesc = {.uuid = nullUuid};
+    const Descriptor::Identity zeroDesc = {.uuid = zeroUuid};
+};
+
+TEST_P(EffectFactoryTest, SetupAndTearDown) {
+    // Intentionally empty test body.
+}
+
+TEST_P(EffectFactoryTest, CanBeRestarted) {
+    ASSERT_NO_FATAL_FAILURE(mFactory.RestartFactoryService());
+}
+
+TEST_P(EffectFactoryTest, QueriedDescriptorList) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    EXPECT_NE(descriptors.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    // TODO: Factory eventually need to return the full list of MUST supported AOSP effects.
+    for (auto& desc : descriptors) {
+        EXPECT_NE(desc.type, zeroUuid);
+        EXPECT_NE(desc.uuid, zeroUuid);
+    }
+}
+
+TEST_P(EffectFactoryTest, QueriedDescriptorNotExistType) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(nullUuid, std::nullopt, &descriptors);
+    EXPECT_EQ(descriptors.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, QueriedDescriptorNotExistInstance) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, nullUuid, &descriptors);
+    EXPECT_EQ(descriptors.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, CreateAndDestroyOnce) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    auto numIds = mFactory.GetEffectIds().size();
+    EXPECT_NE(numIds, 0UL);
+
+    auto& effectMap = mFactory.GetEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    mFactory.DestroyEffects();
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    auto numIds = mFactory.GetEffectIds().size();
+    EXPECT_NE(numIds, 0UL);
+
+    auto& effectMap = mFactory.GetEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    mFactory.DestroyEffects();
+    EXPECT_EQ(effectMap.size(), 0UL);
+
+    // Create and destroy again
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    mFactory.DestroyEffects();
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    auto numIds = mFactory.GetEffectIds().size();
+    EXPECT_NE(numIds, 0UL);
+
+    auto& effectMap = mFactory.GetEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    // Create effect instances of same implementation
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), 2 * numIds);
+
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), 3 * numIds);
+
+    mFactory.DestroyEffects();
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+// Expect EX_ILLEGAL_ARGUMENT when create with invalid UUID.
+TEST_P(EffectFactoryTest, CreateWithInvalidUuid) {
+    std::vector<std::pair<Descriptor::Identity, binder_status_t>> descriptors;
+    descriptors.push_back(std::make_pair(nullDesc, EX_ILLEGAL_ARGUMENT));
+    descriptors.push_back(std::make_pair(zeroDesc, EX_ILLEGAL_ARGUMENT));
+
+    auto& effectMap = mFactory.GetEffectMap();
+    mFactory.CreateEffectsAndExpect(descriptors);
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+// Expect EX_ILLEGAL_ARGUMENT when destroy null interface.
+TEST_P(EffectFactoryTest, DestroyWithInvalidInterface) {
+    std::shared_ptr<IEffect> spDummyEffect(nullptr);
+
+    mFactory.DestroyEffectAndExpect(spDummyEffect, EX_ILLEGAL_ARGUMENT);
+}
+
+TEST_P(EffectFactoryTest, CreateAndRemoveReference) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    auto numIds = mFactory.GetEffectIds().size();
+    EXPECT_NE(numIds, 0UL);
+
+    auto& effectMap = mFactory.GetEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    // remove all reference
+    mFactory.ClearEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, CreateRemoveReferenceAndCreateDestroy) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    auto numIds = mFactory.GetEffectIds().size();
+    EXPECT_NE(numIds, 0UL);
+
+    auto& effectMap = mFactory.GetEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    // remove all reference
+    mFactory.ClearEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+
+    // Create and destroy again
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    mFactory.DestroyEffects();
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, CreateRestartAndCreateDestroy) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    auto numIds = mFactory.GetEffectIds().size();
+    auto& effectMap = mFactory.GetEffectMap();
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    ASSERT_NO_FATAL_FAILURE(mFactory.RestartFactoryService());
+
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    mFactory.DestroyEffects();
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactoryTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EffectFactoryTest);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index 8b5eb13..23b20bd 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -30,205 +30,68 @@
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
+#include <aidl/android/hardware/audio/effect/IEffect.h>
 #include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <aidl/android/media/audio/common/AudioChannelLayout.h>
+#include <aidl/android/media/audio/common/AudioDeviceType.h>
 
 #include "AudioHalBinderServiceUtil.h"
+#include "EffectFactoryHelper.h"
 #include "TestUtils.h"
 
 using namespace android;
 
 using ndk::ScopedAStatus;
 
+using aidl::android::hardware::audio::effect::CommandId;
 using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::IFactory;
-using aidl::android::media::audio::common::AudioUuid;
+using aidl::android::hardware::audio::effect::Parameter;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioDeviceType;
 
-class EffectFactoryHelper {
-  public:
-    explicit EffectFactoryHelper(const std::string& name) : mServiceName(name) {}
-
-    void ConnectToFactoryService() {
-        mEffectFactory = IFactory::fromBinder(binderUtil.connectToService(mServiceName));
-        ASSERT_NE(mEffectFactory, nullptr);
-    }
-
-    void RestartFactoryService() {
-        ASSERT_NE(mEffectFactory, nullptr);
-        mEffectFactory = IFactory::fromBinder(binderUtil.restartService());
-        ASSERT_NE(mEffectFactory, nullptr);
-    }
-
-    void QueryAllEffects() {
-        EXPECT_NE(mEffectFactory, nullptr);
-        EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, &mCompleteIds));
-    }
-
-    void QueryEffects(const std::optional<AudioUuid>& in_type,
-                      const std::optional<AudioUuid>& in_instance,
-                      std::vector<Descriptor::Identity>* _aidl_return) {
-        EXPECT_NE(mEffectFactory, nullptr);
-        EXPECT_IS_OK(mEffectFactory->queryEffects(in_type, in_instance, _aidl_return));
-        mIds = *_aidl_return;
-    }
-
-    void CreateEffects() {
-        EXPECT_NE(mEffectFactory, nullptr);
-        for (const auto& id : mIds) {
-            std::shared_ptr<IEffect> effect;
-            EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
-            EXPECT_NE(effect, nullptr) << id.toString();
-            mEffectIdMap[effect] = id;
-        }
-    }
-
-    void DestroyEffects() {
-        EXPECT_NE(mEffectFactory, nullptr);
-        for (const auto& it : mEffectIdMap) {
-            EXPECT_IS_OK(mEffectFactory->destroyEffect(it.first));
-        }
-        mEffectIdMap.clear();
-    }
-
-    std::shared_ptr<IFactory> GetFactory() { return mEffectFactory; }
-    const std::vector<Descriptor::Identity>& GetEffectIds() { return mIds; }
-    const std::vector<Descriptor::Identity>& GetCompleteEffectIdList() { return mCompleteIds; }
-    const std::unordered_map<std::shared_ptr<IEffect>, Descriptor::Identity>& GetEffectMap() {
-        return mEffectIdMap;
-    }
-
-  private:
-    std::shared_ptr<IFactory> mEffectFactory;
-    std::string mServiceName;
-    AudioHalBinderServiceUtil binderUtil;
-    std::vector<Descriptor::Identity> mIds;
-    std::vector<Descriptor::Identity> mCompleteIds;
-    std::unordered_map<std::shared_ptr<IEffect>, Descriptor::Identity> mEffectIdMap;
-};
-
-/// Effect factory testing.
-class EffectFactoryTest : public testing::TestWithParam<std::string> {
-  public:
-    void SetUp() override { ASSERT_NO_FATAL_FAILURE(mFactory.ConnectToFactoryService()); }
-
-    void TearDown() override { mFactory.DestroyEffects(); }
-
-    EffectFactoryHelper mFactory = EffectFactoryHelper(GetParam());
-
-    // TODO: these UUID can get from config file
-    // ec7178ec-e5e1-4432-a3f4-4657e6795210
-    const AudioUuid nullUuid = {static_cast<int32_t>(0xec7178ec),
-                                0xe5e1,
-                                0x4432,
-                                0xa3f4,
-                                {0x46, 0x57, 0xe6, 0x79, 0x52, 0x10}};
-    const AudioUuid zeroUuid = {
-            static_cast<int32_t>(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
-};
-
-TEST_P(EffectFactoryTest, SetupAndTearDown) {
-    // Intentionally empty test body.
-}
-
-TEST_P(EffectFactoryTest, CanBeRestarted) {
-    ASSERT_NO_FATAL_FAILURE(mFactory.RestartFactoryService());
-}
-
-TEST_P(EffectFactoryTest, QueriedDescriptorList) {
-    std::vector<Descriptor::Identity> descriptors;
-    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
-    EXPECT_NE(descriptors.size(), 0UL);
-}
-
-TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) {
-    std::vector<Descriptor::Identity> descriptors;
-    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
-    // TODO: Factory eventually need to return the full list of MUST supported AOSP effects.
-    for (auto& desc : descriptors) {
-        EXPECT_NE(desc.type, zeroUuid);
-        EXPECT_NE(desc.uuid, zeroUuid);
-    }
-}
-
-TEST_P(EffectFactoryTest, QueriedDescriptorNotExistType) {
-    std::vector<Descriptor::Identity> descriptors;
-    mFactory.QueryEffects(nullUuid, std::nullopt, &descriptors);
-    EXPECT_EQ(descriptors.size(), 0UL);
-}
-
-TEST_P(EffectFactoryTest, QueriedDescriptorNotExistInstance) {
-    std::vector<Descriptor::Identity> descriptors;
-    mFactory.QueryEffects(std::nullopt, nullUuid, &descriptors);
-    EXPECT_EQ(descriptors.size(), 0UL);
-}
-
-TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
-    std::vector<Descriptor::Identity> descriptors;
-    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
-    auto numIds = mFactory.GetEffectIds().size();
-    EXPECT_NE(numIds, 0UL);
-
-    EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
-    mFactory.CreateEffects();
-    EXPECT_EQ(mFactory.GetEffectMap().size(), numIds);
-    mFactory.DestroyEffects();
-    EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
-
-    // Create and destroy again
-    mFactory.CreateEffects();
-    EXPECT_EQ(mFactory.GetEffectMap().size(), numIds);
-    mFactory.DestroyEffects();
-    EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
-}
-
-TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
-    std::vector<Descriptor::Identity> descriptors;
-    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
-    auto numIds = mFactory.GetEffectIds().size();
-    EXPECT_NE(numIds, 0UL);
-
-    EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
-    mFactory.CreateEffects();
-    EXPECT_EQ(mFactory.GetEffectMap().size(), numIds);
-    // Create effect instances of same implementation
-    mFactory.CreateEffects();
-    EXPECT_EQ(mFactory.GetEffectMap().size(), 2 * numIds);
-
-    mFactory.CreateEffects();
-    EXPECT_EQ(mFactory.GetEffectMap().size(), 3 * numIds);
-
-    mFactory.DestroyEffects();
-    EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
-}
-
-INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactoryTest,
-                         testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
-                         android::PrintInstanceNameToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EffectFactoryTest);
-
-/// Effect testing.
 class AudioEffect : public testing::TestWithParam<std::string> {
   public:
     void SetUp() override {
-        ASSERT_NO_FATAL_FAILURE(mFactory.ConnectToFactoryService());
-        ASSERT_NO_FATAL_FAILURE(mFactory.CreateEffects());
+        ASSERT_NO_FATAL_FAILURE(mFactoryHelper.ConnectToFactoryService());
+        CreateEffects();
+        initParamCommon();
+        initParamSpecific();
     }
 
     void TearDown() override {
         CloseEffects();
-        ASSERT_NO_FATAL_FAILURE(mFactory.DestroyEffects());
+        DestroyEffects();
     }
 
     void OpenEffects() {
-        auto open = [](const std::shared_ptr<IEffect>& effect) { EXPECT_IS_OK(effect->open()); };
+        auto open = [&](const std::shared_ptr<IEffect>& effect) {
+            IEffect::OpenEffectReturn ret;
+            EXPECT_IS_OK(effect->open(mCommon, mSpecific, &ret));
+        };
         EXPECT_NO_FATAL_FAILURE(ForEachEffect(open));
     }
 
-    void CloseEffects() {
-        auto close = [](const std::shared_ptr<IEffect>& effect) { EXPECT_IS_OK(effect->close()); };
+    void CloseEffects(const binder_status_t status = EX_NONE) {
+        auto close = [&](const std::shared_ptr<IEffect>& effect) {
+            EXPECT_STATUS(status, effect->close());
+        };
+
         EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
     }
 
+    void CreateEffects(const int n = 1) {
+        for (int i = 0; i < n; i++) {
+            ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateAllEffects());
+        }
+    }
+
+    void DestroyEffects(const binder_status_t status = EX_NONE, const int remaining = 0) {
+        ASSERT_NO_FATAL_FAILURE(mFactoryHelper.DestroyEffects(status, remaining));
+    }
+
     void GetEffectDescriptors() {
         auto get = [](const std::shared_ptr<IEffect>& effect) {
             Descriptor desc;
@@ -237,16 +100,101 @@
         EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
     }
 
+    void CommandEffects(CommandId command) {
+        auto close = [&](const std::shared_ptr<IEffect>& effect) {
+            EXPECT_IS_OK(effect->command(command));
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
+    }
+
+    void CommandEffectsExpectStatus(CommandId command, const binder_status_t status) {
+        auto func = [&](const std::shared_ptr<IEffect>& effect) {
+            EXPECT_STATUS(status, effect->command(command));
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
+    }
+
+    void ExpectState(State expected) {
+        auto get = [&](const std::shared_ptr<IEffect>& effect) {
+            State state = State::INIT;
+            EXPECT_IS_OK(effect->getState(&state));
+            EXPECT_EQ(expected, state);
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
+    }
+
+    void SetParameter() {
+        auto func = [&](const std::shared_ptr<IEffect>& effect) {
+            Parameter param;
+            param.set<Parameter::common>(mCommon);
+            EXPECT_IS_OK(effect->setParameter(param));
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
+    }
+
+    void VerifyParameters() {
+        auto func = [&](const std::shared_ptr<IEffect>& effect) {
+            Parameter paramCommonGet = Parameter(), paramCommonExpect = Parameter();
+            Parameter::Id id;
+            id.set<Parameter::Id::commonTag>(0);
+            paramCommonExpect.set<Parameter::common>(mCommon);
+            EXPECT_IS_OK(effect->getParameter(id, &paramCommonGet));
+            EXPECT_EQ(paramCommonExpect, paramCommonGet)
+                    << paramCommonExpect.toString() << " vs " << paramCommonGet.toString();
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
+    }
+
     template <typename Functor>
     void ForEachEffect(Functor functor) {
-        auto effectMap = mFactory.GetEffectMap();
+        auto effectMap = mFactoryHelper.GetEffectMap();
         for (const auto& it : effectMap) {
             SCOPED_TRACE(it.second.toString());
             functor(it.first);
         }
     }
 
-    EffectFactoryHelper mFactory = EffectFactoryHelper(GetParam());
+    void initParamCommon(int session = -1, int ioHandle = -1,
+                         AudioDeviceType deviceType = AudioDeviceType::NONE,
+                         int iSampleRate = 48000, int oSampleRate = 48000, long iFrameCount = 0x100,
+                         long oFrameCount = 0x100) {
+        mCommon.session = session;
+        mCommon.ioHandle = ioHandle;
+        mCommon.device.type = deviceType;
+        mCommon.input.base.sampleRate = iSampleRate;
+        mCommon.input.base.channelMask = mInputChannelLayout;
+        mCommon.input.frameCount = iFrameCount;
+        mCommon.output.base.sampleRate = oSampleRate;
+        mCommon.output.base.channelMask = mOutputChannelLayout;
+        mCommon.output.frameCount = oFrameCount;
+    }
+
+    void initParamSpecific(Parameter::Specific::Tag tag = Parameter::Specific::equalizer) {
+        switch (tag) {
+            case Parameter::Specific::equalizer:
+                mSpecific.set<Parameter::Specific::equalizer>();
+                break;
+            default:
+                return;
+        }
+    }
+
+    void setInputChannelLayout(AudioChannelLayout input) { mInputChannelLayout = input; }
+    void setOutputChannelLayout(AudioChannelLayout output) { mOutputChannelLayout = output; }
+
+    EffectFactoryHelper mFactoryHelper = EffectFactoryHelper(GetParam());
+
+  private:
+    AudioChannelLayout mInputChannelLayout =
+            AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                    AudioChannelLayout::LAYOUT_STEREO);
+    AudioChannelLayout mOutputChannelLayout =
+            AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                    AudioChannelLayout::LAYOUT_STEREO);
+
+    Parameter::Common mCommon;
+    Parameter::Specific mSpecific;
+    static IEffect::OpenEffectReturn mOpenReturn;
 };
 
 TEST_P(AudioEffect, OpenEffectTest) {
@@ -286,7 +234,7 @@
         Descriptor desc;
         std::vector<Descriptor::Identity> idList;
         EXPECT_IS_OK(effect->getDescriptor(&desc));
-        mFactory.QueryEffects(desc.common.id.type, desc.common.id.uuid, &idList);
+        mFactoryHelper.QueryEffects(desc.common.id.type, desc.common.id.uuid, &idList);
         EXPECT_EQ(idList.size(), 1UL);
     };
     EXPECT_NO_FATAL_FAILURE(ForEachEffect(checker));
@@ -295,7 +243,7 @@
     auto stringHash = [](const Descriptor::Identity& id) {
         return std::hash<std::string>()(id.toString());
     };
-    auto vec = mFactory.GetCompleteEffectIdList();
+    auto vec = mFactoryHelper.GetCompleteEffectIdList();
     std::unordered_set<Descriptor::Identity, decltype(stringHash)> idSet(0, stringHash);
     for (auto it : vec) {
         EXPECT_EQ(idSet.count(it), 0UL);
@@ -303,6 +251,212 @@
     }
 }
 
+/// State testing.
+// An effect instance is in INIT state by default after it was created.
+TEST_P(AudioEffect, InitStateAfterCreation) {
+    ExpectState(State::INIT);
+}
+
+// An effect instance transfer to INIT state after it was open successfully with IEffect.open().
+TEST_P(AudioEffect, IdleStateAfterOpen) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+// An effect instance is in PROCESSING state after it receive an START command.
+TEST_P(AudioEffect, ProcessingStateAfterStart) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+// An effect instance transfer to IDLE state after Command.Id.STOP in PROCESSING state.
+TEST_P(AudioEffect, IdleStateAfterStop) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+// An effect instance transfer to IDLE state after Command.Id.RESET in PROCESSING state.
+TEST_P(AudioEffect, IdleStateAfterReset) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::RESET));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+// An effect instance transfer to INIT if instance receive a close() call.
+TEST_P(AudioEffect, InitStateAfterClose) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+    ExpectState(State::INIT);
+}
+
+// An effect instance shouldn't accept any command before open.
+TEST_P(AudioEffect, NoCommandAcceptedBeforeOpen) {
+    ExpectState(State::INIT);
+    EXPECT_NO_FATAL_FAILURE(CommandEffectsExpectStatus(CommandId::START, EX_ILLEGAL_STATE));
+    EXPECT_NO_FATAL_FAILURE(CommandEffectsExpectStatus(CommandId::STOP, EX_ILLEGAL_STATE));
+    EXPECT_NO_FATAL_FAILURE(CommandEffectsExpectStatus(CommandId::RESET, EX_ILLEGAL_STATE));
+    ExpectState(State::INIT);
+}
+
+// No-op when receive STOP command in IDLE state.
+TEST_P(AudioEffect, StopCommandInIdleStateNoOp) {
+    ExpectState(State::INIT);
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+// No-op when receive STOP command in IDLE state.
+TEST_P(AudioEffect, ResetCommandInIdleStateNoOp) {
+    ExpectState(State::INIT);
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::RESET));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+// Repeat START and STOP command.
+TEST_P(AudioEffect, RepeatStartAndStop) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+// Repeat START and RESET command.
+TEST_P(AudioEffect, RepeatStartAndReset) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::RESET));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::RESET));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+// Repeat START and STOP command, try to close at PROCESSING state.
+TEST_P(AudioEffect, CloseProcessingStateEffects) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    EXPECT_NO_FATAL_FAILURE(CloseEffects(EX_ILLEGAL_STATE));
+    // cleanup
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+    ExpectState(State::IDLE);
+}
+
+// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+TEST_P(AudioEffect, DestroyOpenEffects) {
+    // cleanup all effects.
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+    ASSERT_NO_FATAL_FAILURE(DestroyEffects());
+
+    // open effects, destroy without close, expect to get EX_ILLEGAL_STATE status.
+    EXPECT_NO_FATAL_FAILURE(CreateEffects());
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(DestroyEffects(EX_ILLEGAL_STATE, 1));
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+/// Parameter testing.
+// Verify parameters pass in open can be successfully get.
+TEST_P(AudioEffect, VerifyParametersAfterOpen) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(VerifyParameters());
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+// Verify parameters pass in set can be successfully get.
+TEST_P(AudioEffect, SetAndGetParameter) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(VerifyParameters());
+    initParamCommon(1 /* session */, 1 /* ioHandle */, AudioDeviceType::IN_DEFAULT /* deviceType */,
+                    44100 /* iSampleRate */, 44100 /* oSampleRate */);
+    EXPECT_NO_FATAL_FAILURE(SetParameter());
+    EXPECT_NO_FATAL_FAILURE(VerifyParameters());
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+// Verify parameters pass in set can be successfully get.
+TEST_P(AudioEffect, SetAndGetParameterInProcessing) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(VerifyParameters());
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    initParamCommon(1 /* session */, 1 /* ioHandle */, AudioDeviceType::IN_DEFAULT /* deviceType */,
+                    44100 /* iSampleRate */, 44100 /* oSampleRate */);
+    EXPECT_NO_FATAL_FAILURE(SetParameter());
+    EXPECT_NO_FATAL_FAILURE(VerifyParameters());
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+// Parameters kept after reset.
+TEST_P(AudioEffect, ResetAndVerifyParameter) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(VerifyParameters());
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    initParamCommon(1 /* session */, 1 /* ioHandle */, AudioDeviceType::IN_DEFAULT /* deviceType */,
+                    44100 /* iSampleRate */, 44100 /* oSampleRate */);
+    EXPECT_NO_FATAL_FAILURE(SetParameter());
+    EXPECT_NO_FATAL_FAILURE(VerifyParameters());
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::RESET));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(VerifyParameters());
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+// Multiple instances of same implementation running.
+TEST_P(AudioEffect, MultipleInstancesRunning) {
+    EXPECT_NO_FATAL_FAILURE(CreateEffects(3));
+    ExpectState(State::INIT);
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::START));
+    ExpectState(State::PROCESSING);
+    initParamCommon(1 /* session */, 1 /* ioHandle */, AudioDeviceType::IN_DEFAULT /* deviceType */,
+                    44100 /* iSampleRate */, 44100 /* oSampleRate */);
+    EXPECT_NO_FATAL_FAILURE(SetParameter());
+    EXPECT_NO_FATAL_FAILURE(VerifyParameters());
+    EXPECT_NO_FATAL_FAILURE(CommandEffects(CommandId::STOP));
+    ExpectState(State::IDLE);
+    EXPECT_NO_FATAL_FAILURE(VerifyParameters());
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
 INSTANTIATE_TEST_SUITE_P(AudioEffectTest, AudioEffect,
                          testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
                          android::PrintInstanceNameToString);