Merge "Camera VTS: Improve test for torch callback"
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index d4c1e85..d6e6f50 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -148,6 +148,7 @@
     vendor_available: true,
     srcs: [
         "android/hardware/audio/effect/Descriptor.aidl",
+        "android/hardware/audio/effect/IEffect.aidl",
         "android/hardware/audio/effect/IFactory.aidl",
     ],
     imports: [
@@ -165,3 +166,19 @@
         },
     },
 }
+
+latest_android_hardware_audio_effect = "android.hardware.audio.effect-V1"
+
+cc_defaults {
+    name: "latest_android_hardware_audio_effect_ndk_shared",
+    shared_libs: [
+        latest_android_hardware_audio_effect + "-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "latest_android_hardware_audio_effect_ndk_static",
+    static_libs: [
+        latest_android_hardware_audio_effect + "-ndk",
+    ],
+}
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
new file mode 100644
index 0000000..7f868ad
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.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;
+@VintfStability
+interface IEffect {
+  void open();
+  void close();
+  android.hardware.audio.effect.Descriptor getDescriptor();
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl
index b6c9aab..db06475 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl
@@ -35,4 +35,6 @@
 @VintfStability
 interface IFactory {
   android.hardware.audio.effect.Descriptor.Identity[] queryEffects(in @nullable android.media.audio.common.AudioUuid type, in @nullable android.media.audio.common.AudioUuid implementation);
+  android.hardware.audio.effect.IEffect createEffect(in android.media.audio.common.AudioUuid implUuid);
+  void destroyEffect(in android.hardware.audio.effect.IEffect handle);
 }
diff --git a/audio/aidl/android/hardware/audio/effect/IEffect.aidl b/audio/aidl/android/hardware/audio/effect/IEffect.aidl
new file mode 100644
index 0000000..44e916b
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/IEffect.aidl
@@ -0,0 +1,63 @@
+/*
+ * 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.Descriptor;
+
+/**
+ * Effect interfaces definitions to configure and control the effect instance.
+ */
+@VintfStability
+interface IEffect {
+    /**
+     * 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.
+     *
+     * @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 not result in throw error.
+     */
+    void open();
+
+    /**
+     * Called by the client to close the effect instance, instance context will be kept after
+     * close, but processing thread should be destroyed and consume no CPU. It is recommended to
+     * close the effect on the client side as soon as it becomes unused, it's client responsibility
+     * to make sure all parameter/buffer is correct if client wants to reopen a closed instance.
+     *
+     * Effect instance close interface should always success unless:
+     * 1. The effect instance is not in a proper state to be closed, for example it's still in
+     * 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.
+     * @throws EX_UNSUPPORTED_OPERATION if the effect instance failed to close for any other reason.
+     * @note Close an already-closed effect should do nothing and not result in throw error.
+     */
+    void close();
+
+    /**
+     * Return the @c Descriptor of this effect instance.
+     *
+     * Must be available for the effect instance at anytime and should always succeed.
+     *
+     * @return Descriptor The @c Descriptor of this effect instance.
+     */
+    Descriptor getDescriptor();
+}
diff --git a/audio/aidl/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
index 99c2e6a..4873d3a 100644
--- a/audio/aidl/android/hardware/audio/effect/IFactory.aidl
+++ b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
@@ -17,6 +17,7 @@
 package android.hardware.audio.effect;
 
 import android.hardware.audio.effect.Descriptor;
+import android.hardware.audio.effect.IEffect;
 import android.media.audio.common.AudioUuid;
 
 /**
@@ -42,4 +43,30 @@
      */
     Descriptor.Identity[] queryEffects(
             in @nullable AudioUuid type, in @nullable AudioUuid implementation);
+
+    /**
+     * Called by the audio framework to create the effect (identified by the implementation UUID
+     * parameter).
+     *
+     * The effect instance should be able to maintain its own context and parameters after creation.
+     *
+     * @param implUuid UUID for the effect implementation which instance will be created based on.
+     * @return The effect instance handle created.
+     * @throws EX_ILLEGAL_ARGUMENT if the implUuid is not valid.
+     * @throws EX_TRANSACTION_FAILED if device capability/resource is not enough to create the
+     *         effect instance.
+     */
+    IEffect createEffect(in AudioUuid implUuid);
+
+    /**
+     * Called by the framework to destroy the effect and free up all currently allocated resources.
+     * It is recommended to destroy the effect from the client side as soon as it is becomes unused.
+     *
+     * The client must ensure effect instance is closed before destroy.
+     *
+     * @param handle The handle of effect instance to be destroyed.
+     * @throws EX_ILLEGAL_ARGUMENT if the effect handle is not valid.
+     * @throws EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+     */
+    void destroyEffect(in IEffect handle);
 }
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 5d63347..53ed908 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -68,6 +68,7 @@
         "libbase",
         "libbinder_ndk",
         "android.hardware.audio.effect-V1-ndk",
+        "libequalizer",
     ],
     cflags: [
         "-Wall",
@@ -80,7 +81,10 @@
 cc_library_static {
     name: "libaudioeffectserviceexampleimpl",
     defaults: ["aidlaudioeffectservice_defaults"],
-    export_include_dirs: ["include"],
+    export_include_dirs: [
+        "include",
+        "include/equalizer-impl/",
+    ],
     srcs: [
         "EffectFactory.cpp",
     ],
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
index a31e23f..ea9d470 100644
--- a/audio/aidl/default/EffectFactory.cpp
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -36,6 +36,8 @@
                {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
     id.uuid = EqualizerUUID;
     mIdentityList.push_back(id);
+    // TODO: Add visualizer with default implementation later
+#if 0
     id.type = {static_cast<int32_t>(0xd3467faa),
                0xacc7,
                0x4d34,
@@ -43,6 +45,7 @@
                {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
     id.uuid = VisualizerUUID;
     mIdentityList.push_back(id);
+#endif
 }
 
 ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type,
@@ -56,4 +59,28 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Factory::createEffect(
+        const AudioUuid& in_impl_uuid,
+        std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>* _aidl_return) {
+    LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString();
+    if (in_impl_uuid == EqualizerUUID) {
+        *_aidl_return = ndk::SharedRefBase::make<Equalizer>();
+    } else {
+        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.
+        return ndk::ScopedAStatus::ok();
+    } else {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+}
+
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/EffectMain.cpp b/audio/aidl/default/EffectMain.cpp
index 3b3c39b..b30f2e7 100644
--- a/audio/aidl/default/EffectMain.cpp
+++ b/audio/aidl/default/EffectMain.cpp
@@ -23,10 +23,11 @@
 int main() {
     // This is a debug implementation, always enable debug logging.
     android::base::SetMinimumLogSeverity(::android::base::DEBUG);
-    ABinderProcess_setThreadPoolMaxThreadCount(16);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
 
     auto effectFactory =
             ndk::SharedRefBase::make<aidl::android::hardware::audio::effect::Factory>();
+
     std::string serviceName = std::string() + effectFactory->descriptor + "/default";
     binder_status_t status =
             AServiceManager_addService(effectFactory->asBinder().get(), serviceName.c_str());
diff --git a/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc b/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc
index 01c0e6e..68bbf5b 100644
--- a/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc
+++ b/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc
@@ -2,7 +2,7 @@
     class hal
     user audioserver
     # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
-    group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
+    group audio media
     capabilities BLOCK_SUSPEND
     ioprio rt 4
     task_profiles ProcessCapacityHigh HighPerformance
diff --git a/audio/aidl/default/equalizer/Android.bp b/audio/aidl/default/equalizer/Android.bp
new file mode 100644
index 0000000..b842149
--- /dev/null
+++ b/audio/aidl/default/equalizer/Android.bp
@@ -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.
+ */
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_shared {
+    name: "libequalizer",
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libstagefright_foundation",
+    ],
+    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"],
+    srcs: [
+        "Equalizer.cpp",
+    ],
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
+    ],
+}
diff --git a/audio/aidl/default/equalizer/Equalizer.cpp b/audio/aidl/default/equalizer/Equalizer.cpp
new file mode 100644
index 0000000..dae3ab7
--- /dev/null
+++ b/audio/aidl/default/equalizer/Equalizer.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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_Equalizer"
+#include <android-base/logging.h>
+
+#include "Equalizer.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+Equalizer::Equalizer() {
+    // Implementation UUID
+    mDesc.common.id.uuid = {static_cast<int32_t>(0xce772f20),
+                            0x847d,
+                            0x11df,
+                            0xbb17,
+                            {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+}
+
+ndk::ScopedAStatus Equalizer::open() {
+    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();
+    *_aidl_return = mDesc;
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // 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 7670250..8da5525 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
@@ -40,6 +40,28 @@
             const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_instance,
             std::vector<Descriptor::Identity>* out_descriptor) override;
 
+    /**
+     * @brief Create an effect instance for a certain implementation (identified by UUID).
+     *
+     * @param in_impl_uuid Effect implementation UUID.
+     * @param _aidl_return A pointer to created effect instance.
+     * @return ndk::ScopedAStatus
+     */
+    ndk::ScopedAStatus createEffect(
+            const ::aidl::android::media::audio::common::AudioUuid& in_impl_uuid,
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>* _aidl_return)
+            override;
+
+    /**
+     * @brief Destroy an effect instance.
+     *
+     * @param in_handle Effect instance handle.
+     * @return ndk::ScopedAStatus
+     */
+    ndk::ScopedAStatus destroyEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_handle)
+            override;
+
   private:
     // List of effect descriptors supported by the devices.
     std::vector<Descriptor::Identity> mIdentityList;
diff --git a/audio/aidl/default/include/equalizer-impl/Equalizer.h b/audio/aidl/default/include/equalizer-impl/Equalizer.h
index 86f8c3a..44b1d6d 100644
--- a/audio/aidl/default/include/equalizer-impl/Equalizer.h
+++ b/audio/aidl/default/include/equalizer-impl/Equalizer.h
@@ -16,16 +16,28 @@
 
 #pragma once
 
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
 #include <cstdlib>
 
 namespace aidl::android::hardware::audio::effect {
 
 // Equalizer implementation UUID.
 static const ::aidl::android::media::audio::common::AudioUuid EqualizerUUID = {
-        static_cast<int32_t>(0xce772f20),
-        0x847d,
-        0x11df,
-        0xbb17,
+        static_cast<int32_t>(0x0bed4300),
+        0xddd6,
+        0x11db,
+        0x8f34,
         {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
 
-}  // namespace aidl::android::hardware::audio::effect
\ No newline at end of file
+class Equalizer : public BnEffect {
+  public:
+    Equalizer();
+    ndk::ScopedAStatus open() override;
+    ndk::ScopedAStatus close() override;
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+
+  private:
+    // Effect descriptor.
+    Descriptor mDesc = {.common.id.type = EqualizerUUID};
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/vts/TestUtils.h b/audio/aidl/vts/TestUtils.h
new file mode 100644
index 0000000..2fc109a
--- /dev/null
+++ b/audio/aidl/vts/TestUtils.h
@@ -0,0 +1,73 @@
+/*
+ * 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 <iostream>
+
+#include <android/binder_auto_utils.h>
+#include <gtest/gtest_pred_impl.h>
+
+namespace ndk {
+
+std::ostream& operator<<(std::ostream& str, const ScopedAStatus& status) {
+    str << status.getDescription();
+    return str;
+}
+
+}  // namespace ndk
+
+namespace android::hardware::audio::common::testing {
+
+namespace detail {
+
+inline ::testing::AssertionResult assertIsOk(const char* expr, const ::ndk::ScopedAStatus& status) {
+    if (status.isOk()) {
+        return ::testing::AssertionSuccess();
+    }
+    return ::testing::AssertionFailure()
+           << "Expected the transaction \'" << expr << "\' to succeed\n"
+           << "  but it has failed with: " << status;
+}
+
+inline ::testing::AssertionResult assertResult(const char* exp_expr, const char* act_expr,
+                                               int32_t expected,
+                                               const ::ndk::ScopedAStatus& status) {
+    if (status.getExceptionCode() == expected) {
+        return ::testing::AssertionSuccess();
+    }
+    return ::testing::AssertionFailure()
+           << "Expected the transaction \'" << act_expr << "\' to fail with " << exp_expr
+           << "\n  but is has completed with: " << status;
+}
+
+}  // namespace detail
+
+}  // namespace android::hardware::audio::common::testing
+
+// Test that the transaction status 'isOk'
+#define ASSERT_IS_OK(ret) \
+    ASSERT_PRED_FORMAT1(::android::hardware::audio::common::testing::detail::assertIsOk, ret)
+#define EXPECT_IS_OK(ret) \
+    EXPECT_PRED_FORMAT1(::android::hardware::audio::common::testing::detail::assertIsOk, ret)
+
+// Test that the transaction status is as expected.
+#define ASSERT_STATUS(expected, ret)                                                       \
+    ASSERT_PRED_FORMAT2(::android::hardware::audio::common::testing::detail::assertResult, \
+                        expected, ret)
+#define EXPECT_STATUS(expected, ret)                                                       \
+    EXPECT_PRED_FORMAT2(::android::hardware::audio::common::testing::detail::assertResult, \
+                        expected, ret)
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
index 2659f79..2381200 100644
--- a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
@@ -38,6 +38,7 @@
 
 #include "AudioHalBinderServiceUtil.h"
 #include "ModuleConfig.h"
+#include "TestUtils.h"
 
 using namespace android;
 using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
@@ -70,13 +71,6 @@
 using android::hardware::audio::common::StreamWorker;
 using ndk::ScopedAStatus;
 
-namespace ndk {
-std::ostream& operator<<(std::ostream& str, const ScopedAStatus& status) {
-    str << status.getDescription();
-    return str;
-}
-}  // namespace ndk
-
 template <typename T>
 auto findById(std::vector<T>& v, int32_t id) {
     return std::find_if(v.begin(), v.end(), [&](const auto& e) { return e.id == id; });
@@ -113,14 +107,10 @@
     WithDebugFlags& operator=(const WithDebugFlags&) = delete;
     ~WithDebugFlags() {
         if (mModule != nullptr) {
-            ScopedAStatus status = mModule->setModuleDebug(mInitial);
-            EXPECT_EQ(EX_NONE, status.getExceptionCode()) << status;
+            EXPECT_IS_OK(mModule->setModuleDebug(mInitial));
         }
     }
-    void SetUp(IModule* module) {
-        ScopedAStatus status = module->setModuleDebug(mFlags);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    void SetUp(IModule* module) { ASSERT_IS_OK(module->setModuleDebug(mFlags)); }
     ModuleDebug& flags() { return mFlags; }
 
   private:
@@ -141,9 +131,7 @@
     WithAudioPortConfig& operator=(const WithAudioPortConfig&) = delete;
     ~WithAudioPortConfig() {
         if (mModule != nullptr) {
-            ScopedAStatus status = mModule->resetAudioPortConfig(getId());
-            EXPECT_EQ(EX_NONE, status.getExceptionCode())
-                    << status << "; port config id " << getId();
+            EXPECT_IS_OK(mModule->resetAudioPortConfig(getId())) << "port config id " << getId();
         }
     }
     void SetUp(IModule* module) {
@@ -162,9 +150,8 @@
         if (mInitialConfig.id == 0) {
             AudioPortConfig suggested;
             bool applied = false;
-            ScopedAStatus status = module->setAudioPortConfig(mInitialConfig, &suggested, &applied);
-            ASSERT_EQ(EX_NONE, status.getExceptionCode())
-                    << status << "; Config: " << mInitialConfig.toString();
+            ASSERT_IS_OK(module->setAudioPortConfig(mInitialConfig, &suggested, &applied))
+                    << "Config: " << mInitialConfig.toString();
             if (!applied && negotiate) {
                 mInitialConfig = suggested;
                 ASSERT_NO_FATAL_FAILURE(SetUpImpl(module, false))
@@ -197,9 +184,7 @@
 
     void TearDown() override {
         if (module != nullptr) {
-            ScopedAStatus status = module->setModuleDebug(ModuleDebug{});
-            EXPECT_EQ(EX_NONE, status.getExceptionCode())
-                    << status << " returned when resetting debug flags";
+            EXPECT_IS_OK(module->setModuleDebug(ModuleDebug{}));
         }
     }
 
@@ -222,8 +207,7 @@
             ASSERT_NO_FATAL_FAILURE(portConfig.SetUp(module.get()));  // calls setAudioPortConfig
             EXPECT_EQ(config.portId, portConfig.get().portId);
             std::vector<AudioPortConfig> retrievedPortConfigs;
-            ScopedAStatus status = module->getAudioPortConfigs(&retrievedPortConfigs);
-            ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
+            ASSERT_IS_OK(module->getAudioPortConfigs(&retrievedPortConfigs));
             const int32_t portConfigId = portConfig.getId();
             auto configIt = std::find_if(
                     retrievedPortConfigs.begin(), retrievedPortConfigs.end(),
@@ -246,10 +230,7 @@
                          ScopedAStatus (IModule::*getter)(std::vector<Entity>*),
                          const std::string& errorMessage) {
         std::vector<Entity> entities;
-        {
-            ScopedAStatus status = (module.get()->*getter)(&entities);
-            ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-        }
+        { ASSERT_IS_OK((module.get()->*getter)(&entities)); }
         std::transform(entities.begin(), entities.end(),
                        std::inserter(*entityIds, entityIds->begin()),
                        [](const auto& entity) { return entity.id; });
@@ -297,16 +278,13 @@
     WithDevicePortConnectedState& operator=(const WithDevicePortConnectedState&) = delete;
     ~WithDevicePortConnectedState() {
         if (mModule != nullptr) {
-            ScopedAStatus status = mModule->disconnectExternalDevice(getId());
-            EXPECT_EQ(EX_NONE, status.getExceptionCode())
-                    << status << " returned when disconnecting device port ID " << getId();
+            EXPECT_IS_OK(mModule->disconnectExternalDevice(getId()))
+                    << "when disconnecting device port ID " << getId();
         }
     }
     void SetUp(IModule* module) {
-        ScopedAStatus status = module->connectExternalDevice(mIdAndData, &mConnectedPort);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode())
-                << status << " returned when connecting device port ID & data "
-                << mIdAndData.toString();
+        ASSERT_IS_OK(module->connectExternalDevice(mIdAndData, &mConnectedPort))
+                << "when connecting device port ID & data " << mIdAndData.toString();
         ASSERT_NE(mIdAndData.id, getId())
                 << "ID of the connected port must not be the same as the ID of the template port";
         mModule = module;
@@ -544,9 +522,7 @@
     ~WithStream() {
         if (mStream != nullptr) {
             mContext.reset();
-            ScopedAStatus status = mStream->close();
-            EXPECT_EQ(EX_NONE, status.getExceptionCode())
-                    << status << "; port config id " << getPortId();
+            EXPECT_IS_OK(mStream->close()) << "port config id " << getPortId();
         }
     }
     void SetUpPortConfig(IModule* module) { ASSERT_NO_FATAL_FAILURE(mPortConfig.SetUp(module)); }
@@ -557,10 +533,8 @@
                                 long bufferSizeFrames);
     void SetUp(IModule* module, long bufferSizeFrames) {
         ASSERT_NO_FATAL_FAILURE(SetUpPortConfig(module));
-        ScopedAStatus status = SetUpNoChecks(module, bufferSizeFrames);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode())
-                << status << "; port config id " << getPortId();
-        ASSERT_NE(nullptr, mStream) << "; port config id " << getPortId();
+        ASSERT_IS_OK(SetUpNoChecks(module, bufferSizeFrames)) << "port config id " << getPortId();
+        ASSERT_NE(nullptr, mStream) << "port config id " << getPortId();
         EXPECT_GE(mDescriptor.bufferSizeFrames, bufferSizeFrames)
                 << "actual buffer size must be no less than requested";
         mContext.emplace(mDescriptor);
@@ -648,8 +622,7 @@
     WithAudioPatch& operator=(const WithAudioPatch&) = delete;
     ~WithAudioPatch() {
         if (mModule != nullptr && mPatch.id != 0) {
-            ScopedAStatus status = mModule->resetAudioPatch(mPatch.id);
-            EXPECT_EQ(EX_NONE, status.getExceptionCode()) << status << "; patch id " << getId();
+            EXPECT_IS_OK(mModule->resetAudioPatch(mPatch.id)) << "patch id " << getId();
         }
     }
     void SetUpPortConfigs(IModule* module) {
@@ -664,10 +637,8 @@
     }
     void SetUp(IModule* module) {
         ASSERT_NO_FATAL_FAILURE(SetUpPortConfigs(module));
-        ScopedAStatus status = SetUpNoChecks(module);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode())
-                << status << "; source port config id " << mSrcPortConfig.getId()
-                << "; sink port config id " << mSinkPortConfig.getId();
+        ASSERT_IS_OK(SetUpNoChecks(module)) << "source port config id " << mSrcPortConfig.getId()
+                                            << "; sink port config id " << mSinkPortConfig.getId();
         EXPECT_GT(mPatch.minimumStreamBufferSizeFrames, 0) << "patch id " << getId();
         for (auto latencyMs : mPatch.latenciesMs) {
             EXPECT_GT(latencyMs, 0) << "patch id " << getId();
@@ -703,15 +674,9 @@
 
 TEST_P(AudioCoreModule, GetAudioPortsIsStable) {
     std::vector<AudioPort> ports1;
-    {
-        ScopedAStatus status = module->getAudioPorts(&ports1);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    ASSERT_IS_OK(module->getAudioPorts(&ports1));
     std::vector<AudioPort> ports2;
-    {
-        ScopedAStatus status = module->getAudioPorts(&ports2);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    ASSERT_IS_OK(module->getAudioPorts(&ports2));
     ASSERT_EQ(ports1.size(), ports2.size())
             << "Sizes of audio port arrays do not match across consequent calls to getAudioPorts";
     std::sort(ports1.begin(), ports1.end());
@@ -721,15 +686,9 @@
 
 TEST_P(AudioCoreModule, GetAudioRoutesIsStable) {
     std::vector<AudioRoute> routes1;
-    {
-        ScopedAStatus status = module->getAudioRoutes(&routes1);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    ASSERT_IS_OK(module->getAudioRoutes(&routes1));
     std::vector<AudioRoute> routes2;
-    {
-        ScopedAStatus status = module->getAudioRoutes(&routes2);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    ASSERT_IS_OK(module->getAudioRoutes(&routes2));
     ASSERT_EQ(routes1.size(), routes2.size())
             << "Sizes of audio route arrays do not match across consequent calls to getAudioRoutes";
     std::sort(routes1.begin(), routes1.end());
@@ -739,10 +698,7 @@
 
 TEST_P(AudioCoreModule, GetAudioRoutesAreValid) {
     std::vector<AudioRoute> routes;
-    {
-        ScopedAStatus status = module->getAudioRoutes(&routes);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    ASSERT_IS_OK(module->getAudioRoutes(&routes));
     for (const auto& route : routes) {
         std::set<int32_t> sources(route.sourcePortIds.begin(), route.sourcePortIds.end());
         EXPECT_NE(0UL, sources.size())
@@ -757,10 +713,7 @@
     std::set<int32_t> portIds;
     ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
     std::vector<AudioRoute> routes;
-    {
-        ScopedAStatus status = module->getAudioRoutes(&routes);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    ASSERT_IS_OK(module->getAudioRoutes(&routes));
     for (const auto& route : routes) {
         EXPECT_EQ(1UL, portIds.count(route.sinkPortId))
                 << route.sinkPortId << " sink port id is unknown";
@@ -778,8 +731,7 @@
     }
     for (const auto portId : portIds) {
         std::vector<AudioRoute> routes;
-        ScopedAStatus status = module->getAudioRoutesForAudioPort(portId, &routes);
-        EXPECT_EQ(EX_NONE, status.getExceptionCode()) << status;
+        EXPECT_IS_OK(module->getAudioRoutesForAudioPort(portId, &routes));
         for (const auto& r : routes) {
             if (r.sinkPortId != portId) {
                 const auto& srcs = r.sourcePortIds;
@@ -790,18 +742,14 @@
     }
     for (const auto portId : GetNonExistentIds(portIds)) {
         std::vector<AudioRoute> routes;
-        ScopedAStatus status = module->getAudioRoutesForAudioPort(portId, &routes);
-        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << " returned for port ID " << portId;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->getAudioRoutesForAudioPort(portId, &routes))
+                << "port ID " << portId;
     }
 }
 
 TEST_P(AudioCoreModule, CheckDevicePorts) {
     std::vector<AudioPort> ports;
-    {
-        ScopedAStatus status = module->getAudioPorts(&ports);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    ASSERT_IS_OK(module->getAudioPorts(&ports));
     std::optional<int32_t> defaultOutput, defaultInput;
     std::set<AudioDevice> inputs, outputs;
     const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
@@ -847,10 +795,7 @@
 
 TEST_P(AudioCoreModule, CheckMixPorts) {
     std::vector<AudioPort> ports;
-    {
-        ScopedAStatus status = module->getAudioPorts(&ports);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    ASSERT_IS_OK(module->getAudioPorts(&ports));
     std::optional<int32_t> primaryMixPort;
     for (const auto& port : ports) {
         if (port.ext.getTag() != AudioPortExt::Tag::mix) continue;
@@ -877,15 +822,13 @@
     }
     for (const auto portId : portIds) {
         AudioPort port;
-        ScopedAStatus status = module->getAudioPort(portId, &port);
-        EXPECT_EQ(EX_NONE, status.getExceptionCode()) << status;
+        EXPECT_IS_OK(module->getAudioPort(portId, &port));
         EXPECT_EQ(portId, port.id);
     }
     for (const auto portId : GetNonExistentIds(portIds)) {
         AudioPort port;
-        ScopedAStatus status = module->getAudioPort(portId, &port);
-        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << " returned for port ID " << portId;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->getAudioPort(portId, &port))
+                << "port ID " << portId;
     }
 }
 
@@ -917,9 +860,8 @@
                   portConnected.get().ext.get<AudioPortExt::Tag::device>().device);
         // Verify that 'getAudioPort' and 'getAudioPorts' return the same connected port.
         AudioPort connectedPort;
-        ScopedAStatus status = module->getAudioPort(connectedPortId, &connectedPort);
-        EXPECT_EQ(EX_NONE, status.getExceptionCode())
-                << status << " returned for getAudioPort port ID " << connectedPortId;
+        EXPECT_IS_OK(module->getAudioPort(connectedPortId, &connectedPort))
+                << "port ID " << connectedPortId;
         EXPECT_EQ(portConnected.get(), connectedPort);
         const auto& portProfiles = connectedPort.profiles;
         EXPECT_NE(0UL, portProfiles.size())
@@ -932,10 +874,7 @@
                                                         << "profiles: " << connectedPort.toString();
 
         std::vector<AudioPort> allPorts;
-        {
-            ScopedAStatus status = module->getAudioPorts(&allPorts);
-            ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-        }
+        ASSERT_IS_OK(module->getAudioPorts(&allPorts));
         const auto allPortsIt = findById(allPorts, connectedPortId);
         EXPECT_NE(allPorts.end(), allPortsIt);
         if (allPortsIt != allPorts.end()) {
@@ -953,9 +892,8 @@
             args.portConfigId = portConfigId;
             args.bufferSizeFrames = kDefaultBufferSizeFrames;
             aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
-            ScopedAStatus status = module->openInputStream(args, &ret);
-            EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                    << status << " openInputStream returned for port config ID " << portConfigId;
+            EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openInputStream(args, &ret))
+                    << "port config ID " << portConfigId;
             EXPECT_EQ(nullptr, ret.stream);
         }
         {
@@ -963,9 +901,8 @@
             args.portConfigId = portConfigId;
             args.bufferSizeFrames = kDefaultBufferSizeFrames;
             aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
-            ScopedAStatus status = module->openOutputStream(args, &ret);
-            EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                    << status << " openOutputStream returned for port config ID " << portConfigId;
+            EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openOutputStream(args, &ret))
+                    << "port config ID " << portConfigId;
             EXPECT_EQ(nullptr, ret.stream);
         }
     }
@@ -980,10 +917,7 @@
     std::set<int32_t> portIds;
     ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
     std::vector<AudioPortConfig> portConfigs;
-    {
-        ScopedAStatus status = module->getAudioPortConfigs(&portConfigs);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    ASSERT_IS_OK(module->getAudioPortConfigs(&portConfigs));
     for (const auto& config : portConfigs) {
         EXPECT_EQ(1UL, portIds.count(config.portId))
                 << config.portId << " port id is unknown, config id " << config.id;
@@ -994,9 +928,8 @@
     std::set<int32_t> portConfigIds;
     ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
     for (const auto portConfigId : GetNonExistentIds(portConfigIds)) {
-        ScopedAStatus status = module->resetAudioPortConfig(portConfigId);
-        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << " returned for port config ID " << portConfigId;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->resetAudioPortConfig(portConfigId))
+                << "port config ID " << portConfigId;
     }
 }
 
@@ -1004,21 +937,13 @@
 // the config does not delete it, but brings it back to the initial config.
 TEST_P(AudioCoreModule, ResetAudioPortConfigToInitialValue) {
     std::vector<AudioPortConfig> portConfigsBefore;
-    {
-        ScopedAStatus status = module->getAudioPortConfigs(&portConfigsBefore);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    ASSERT_IS_OK(module->getAudioPortConfigs(&portConfigsBefore));
     // TODO: Change port configs according to port profiles.
     for (const auto& c : portConfigsBefore) {
-        ScopedAStatus status = module->resetAudioPortConfig(c.id);
-        EXPECT_EQ(EX_NONE, status.getExceptionCode())
-                << status << " returned for port config ID " << c.id;
+        EXPECT_IS_OK(module->resetAudioPortConfig(c.id)) << "port config ID " << c.id;
     }
     std::vector<AudioPortConfig> portConfigsAfter;
-    {
-        ScopedAStatus status = module->getAudioPortConfigs(&portConfigsAfter);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    ASSERT_IS_OK(module->getAudioPortConfigs(&portConfigsAfter));
     for (const auto& c : portConfigsBefore) {
         auto afterIt = findById<AudioPortConfig>(portConfigsAfter, c.id);
         EXPECT_NE(portConfigsAfter.end(), afterIt)
@@ -1040,9 +965,8 @@
     portConfig.portId = srcMixPort.value().id;
     {
         bool applied = true;
-        ScopedAStatus status = module->setAudioPortConfig(portConfig, &suggestedConfig, &applied);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode())
-                << status << "; Config: " << portConfig.toString();
+        ASSERT_IS_OK(module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
+                << "Config: " << portConfig.toString();
         EXPECT_FALSE(applied);
     }
     EXPECT_EQ(0, suggestedConfig.id);
@@ -1096,9 +1020,9 @@
         AudioPortConfig portConfig, suggestedConfig;
         bool applied;
         portConfig.portId = portId;
-        ScopedAStatus status = module->setAudioPortConfig(portConfig, &suggestedConfig, &applied);
-        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << " returned for port ID " << portId;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+                      module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
+                << "port ID " << portId;
         EXPECT_FALSE(suggestedConfig.format.has_value());
         EXPECT_FALSE(suggestedConfig.channelMask.has_value());
         EXPECT_FALSE(suggestedConfig.sampleRate.has_value());
@@ -1112,9 +1036,9 @@
         AudioPortConfig portConfig, suggestedConfig;
         bool applied;
         portConfig.id = portConfigId;
-        ScopedAStatus status = module->setAudioPortConfig(portConfig, &suggestedConfig, &applied);
-        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << " returned for port config ID " << portConfigId;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+                      module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
+                << "port config ID " << portConfigId;
         EXPECT_FALSE(suggestedConfig.format.has_value());
         EXPECT_FALSE(suggestedConfig.channelMask.has_value());
         EXPECT_FALSE(suggestedConfig.sampleRate.has_value());
@@ -1135,9 +1059,8 @@
         AudioPort portWithData = port;
         portWithData.ext.get<AudioPortExt::Tag::device>().device.address =
                 GenerateUniqueDeviceAddress();
-        ScopedAStatus status = module->connectExternalDevice(portWithData, &ignored);
-        EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
-                << status << " returned for static port " << portWithData.toString();
+        EXPECT_STATUS(EX_ILLEGAL_STATE, module->connectExternalDevice(portWithData, &ignored))
+                << "static port " << portWithData.toString();
     }
 }
 
@@ -1151,10 +1074,8 @@
     ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
     ModuleDebug midwayDebugChange = debug.flags();
     midwayDebugChange.simulateDeviceConnections = false;
-    ScopedAStatus status = module->setModuleDebug(midwayDebugChange);
-    EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
-            << status << " returned when trying to disable connections simulation "
-            << "while having a connected device";
+    EXPECT_STATUS(EX_ILLEGAL_STATE, module->setModuleDebug(midwayDebugChange))
+            << "when trying to disable connections simulation while having a connected device";
 }
 
 TEST_P(AudioCoreModule, ConnectDisconnectExternalDeviceInvalidPorts) {
@@ -1164,40 +1085,28 @@
     for (const auto portId : GetNonExistentIds(portIds)) {
         AudioPort invalidPort;
         invalidPort.id = portId;
-        ScopedAStatus status = module->connectExternalDevice(invalidPort, &ignored);
-        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << " returned for port ID " << portId << " when setting CONNECTED state";
-        status = module->disconnectExternalDevice(portId);
-        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << " returned for port ID " << portId
-                << " when setting DISCONNECTED state";
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->connectExternalDevice(invalidPort, &ignored))
+                << "port ID " << portId << ", when setting CONNECTED state";
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(portId))
+                << "port ID " << portId << ", when setting DISCONNECTED state";
     }
 
     std::vector<AudioPort> ports;
-    {
-        ScopedAStatus status = module->getAudioPorts(&ports);
-        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-    }
+    ASSERT_IS_OK(module->getAudioPorts(&ports));
     for (const auto& port : ports) {
         if (port.ext.getTag() != AudioPortExt::Tag::device) {
-            ScopedAStatus status = module->connectExternalDevice(port, &ignored);
-            EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                    << status << " returned for non-device port ID " << port.id
-                    << " when setting CONNECTED state";
-            status = module->disconnectExternalDevice(port.id);
-            EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                    << status << " returned for non-device port ID " << port.id
-                    << " when setting DISCONNECTED state";
+            EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->connectExternalDevice(port, &ignored))
+                    << "non-device port ID " << port.id << " when setting CONNECTED state";
+            EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(port.id))
+                    << "non-device port ID " << port.id << " when setting DISCONNECTED state";
         } else {
             const auto& devicePort = port.ext.get<AudioPortExt::Tag::device>();
             if (devicePort.device.type.connection.empty()) {
-                ScopedAStatus status = module->connectExternalDevice(port, &ignored);
-                EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                        << status << " returned for permanently attached device port ID " << port.id
+                EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->connectExternalDevice(port, &ignored))
+                        << "for a permanently attached device port ID " << port.id
                         << " when setting CONNECTED state";
-                status = module->disconnectExternalDevice(port.id);
-                EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                        << status << " returned for permanently attached device port ID " << port.id
+                EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(port.id))
+                        << "for a permanently attached device port ID " << port.id
                         << " when setting DISCONNECTED state";
             }
         }
@@ -1213,27 +1122,22 @@
         GTEST_SKIP() << "No external devices in the module.";
     }
     for (const auto& port : ports) {
-        ScopedAStatus status = module->disconnectExternalDevice(port.id);
-        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << " returned when disconnecting already disconnected device port ID "
-                << port.id;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(port.id))
+                << "when disconnecting already disconnected device port ID " << port.id;
         AudioPort portWithData = port;
         portWithData.ext.get<AudioPortExt::Tag::device>().device.address =
                 GenerateUniqueDeviceAddress();
         WithDevicePortConnectedState portConnected(portWithData);
         ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
-        status = module->connectExternalDevice(portConnected.get(), &ignored);
-        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << " returned when trying to connect a connected device port "
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+                      module->connectExternalDevice(portConnected.get(), &ignored))
+                << "when trying to connect a connected device port "
                 << portConnected.get().toString();
-        status = module->connectExternalDevice(portWithData, &ignored);
-        EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
-                << status << " returned when connecting again the external device "
-                << portWithData.ext.get<AudioPortExt::Tag::device>().device.toString();
-        if (status.getExceptionCode() == EX_NONE) {
-            ADD_FAILURE() << "Returned connected port " << ignored.toString() << " for template "
-                          << portWithData.toString();
-        }
+        EXPECT_STATUS(EX_ILLEGAL_STATE, module->connectExternalDevice(portWithData, &ignored))
+                << "when connecting again the external device "
+                << portWithData.ext.get<AudioPortExt::Tag::device>().device.toString()
+                << "; Returned connected port " << ignored.toString() << " for template "
+                << portWithData.toString();
     }
 }
 
@@ -1254,9 +1158,8 @@
             // Our test assumes that 'getAudioPort' returns at least one profile, and it
             // is not a dynamic profile.
             ASSERT_NO_FATAL_FAILURE(config.SetUp(module.get()));
-            ScopedAStatus status = module->disconnectExternalDevice(portConnected.getId());
-            EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
-                    << status << " returned when trying to disconnect device port ID " << port.id
+            EXPECT_STATUS(EX_ILLEGAL_STATE, module->disconnectExternalDevice(portConnected.getId()))
+                    << "when trying to disconnect device port ID " << port.id
                     << " with active configuration " << config.getId();
         }
     }
@@ -1270,10 +1173,7 @@
     }
     for (const auto& port : ports) {
         std::vector<AudioRoute> routesBefore;
-        {
-            ScopedAStatus status = module->getAudioRoutes(&routesBefore);
-            ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-        }
+        ASSERT_IS_OK(module->getAudioRoutes(&routesBefore));
 
         int32_t connectedPortId;
         {
@@ -1281,34 +1181,24 @@
             ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
             connectedPortId = portConnected.getId();
             std::vector<AudioRoute> connectedPortRoutes;
-            {
-                ScopedAStatus status =
-                        module->getAudioRoutesForAudioPort(connectedPortId, &connectedPortRoutes);
-                ASSERT_EQ(EX_NONE, status.getExceptionCode())
-                        << status << " returned when retrieving routes for connected port id "
-                        << connectedPortId;
-            }
+            ASSERT_IS_OK(module->getAudioRoutesForAudioPort(connectedPortId, &connectedPortRoutes))
+                    << "when retrieving routes for connected port id " << connectedPortId;
             // There must be routes for the port to be useful.
             if (connectedPortRoutes.empty()) {
                 std::vector<AudioRoute> allRoutes;
-                ScopedAStatus status = module->getAudioRoutes(&allRoutes);
-                ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
+                ASSERT_IS_OK(module->getAudioRoutes(&allRoutes));
                 ADD_FAILURE() << " no routes returned for the connected port "
                               << portConnected.get().toString()
                               << "; all routes: " << android::internal::ToString(allRoutes);
             }
         }
         std::vector<AudioRoute> ignored;
-        ScopedAStatus status = module->getAudioRoutesForAudioPort(connectedPortId, &ignored);
-        ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << " returned when retrieving routes for released connected port id "
-                << connectedPortId;
+        ASSERT_STATUS(EX_ILLEGAL_ARGUMENT,
+                      module->getAudioRoutesForAudioPort(connectedPortId, &ignored))
+                << "when retrieving routes for released connected port id " << connectedPortId;
 
         std::vector<AudioRoute> routesAfter;
-        {
-            ScopedAStatus status = module->getAudioRoutes(&routesAfter);
-            ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
-        }
+        ASSERT_IS_OK(module->getAudioRoutes(&routesAfter));
         ASSERT_EQ(routesBefore.size(), routesAfter.size())
                 << "Sizes of audio route arrays do not match after creating and "
                 << "releasing a connected port";
@@ -1321,8 +1211,6 @@
 template <typename Stream>
 class AudioStream : public AudioCoreModule {
   public:
-    static std::string direction(bool capitalize);
-
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(AudioCoreModule::SetUp());
         ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
@@ -1339,9 +1227,7 @@
             ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
             heldStream = stream.getSharedPointer();
         }
-        ScopedAStatus status = heldStream->close();
-        EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
-                << status << " when closing the stream twice";
+        EXPECT_STATUS(EX_ILLEGAL_STATE, heldStream->close()) << "when closing the stream twice";
     }
 
     void OpenAllConfigs() {
@@ -1363,10 +1249,8 @@
         // The buffer size of 1 frame should be impractically small, and thus
         // less than any minimum buffer size suggested by any HAL.
         for (long bufferSize : std::array<long, 4>{-1, 0, 1, std::numeric_limits<long>::max()}) {
-            ScopedAStatus status = stream.SetUpNoChecks(module.get(), bufferSize);
-            EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                    << status << " open" << direction(true) << "Stream returned for " << bufferSize
-                    << " buffer size";
+            EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, stream.SetUpNoChecks(module.get(), bufferSize))
+                    << "for the buffer size " << bufferSize;
             EXPECT_EQ(nullptr, stream.get());
         }
     }
@@ -1380,10 +1264,9 @@
         }
         WithStream<Stream> stream(portConfig.value());
         ASSERT_NO_FATAL_FAILURE(stream.SetUpPortConfig(module.get()));
-        ScopedAStatus status = stream.SetUpNoChecks(module.get(), kDefaultBufferSizeFrames);
-        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << " open" << direction(true) << "Stream returned for port config ID "
-                << stream.getPortId();
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+                      stream.SetUpNoChecks(module.get(), kDefaultBufferSizeFrames))
+                << "port config ID " << stream.getPortId();
         EXPECT_EQ(nullptr, stream.get());
     }
 
@@ -1412,18 +1295,15 @@
                     ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
                 } else {
                     ASSERT_NO_FATAL_FAILURE(stream.SetUpPortConfig(module.get()));
-                    ScopedAStatus status =
-                            stream.SetUpNoChecks(module.get(), kDefaultBufferSizeFrames);
-                    EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
-                            << status << " open" << direction(true)
-                            << "Stream returned for port config ID " << stream.getPortId()
-                            << ", maxOpenStreamCount is " << maxStreamCount;
+                    EXPECT_STATUS(EX_ILLEGAL_STATE,
+                                  stream.SetUpNoChecks(module.get(), kDefaultBufferSizeFrames))
+                            << "port config ID " << stream.getPortId() << ", maxOpenStreamCount is "
+                            << maxStreamCount;
                 }
             }
         }
         if (!hasSingleRun) {
-            GTEST_SKIP() << "Not enough " << direction(false)
-                         << " ports to test max open stream count";
+            GTEST_SKIP() << "Not enough ports to test max open stream count";
         }
     }
 
@@ -1455,9 +1335,8 @@
         }
         WithStream<Stream> stream(portConfig.value());
         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
-        ScopedAStatus status = module->resetAudioPortConfig(stream.getPortId());
-        EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
-                << status << " returned for port config ID " << stream.getPortId();
+        EXPECT_STATUS(EX_ILLEGAL_STATE, module->resetAudioPortConfig(stream.getPortId()))
+                << "port config ID " << stream.getPortId();
     }
 
     void SendInvalidCommand() {
@@ -1472,11 +1351,10 @@
         WithStream<Stream> stream1(portConfig);
         ASSERT_NO_FATAL_FAILURE(stream1.SetUp(module.get(), kDefaultBufferSizeFrames));
         WithStream<Stream> stream2;
-        ScopedAStatus status = stream2.SetUpNoChecks(module.get(), stream1.getPortConfig(),
-                                                     kDefaultBufferSizeFrames);
-        EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
-                << status << " when opening " << direction(false)
-                << " stream twice for the same port config ID " << stream1.getPortId();
+        EXPECT_STATUS(EX_ILLEGAL_STATE, stream2.SetUpNoChecks(module.get(), stream1.getPortConfig(),
+                                                              kDefaultBufferSizeFrames))
+                << "when opening a stream twice for the same port config ID "
+                << stream1.getPortId();
     }
 
     template <class Worker>
@@ -1576,15 +1454,6 @@
 using AudioStreamIn = AudioStream<IStreamIn>;
 using AudioStreamOut = AudioStream<IStreamOut>;
 
-template <>
-std::string AudioStreamIn::direction(bool capitalize) {
-    return capitalize ? "Input" : "input";
-}
-template <>
-std::string AudioStreamOut::direction(bool capitalize) {
-    return capitalize ? "Output" : "output";
-}
-
 #define TEST_IO_STREAM(method_name)                                                \
     TEST_P(AudioStreamIn, method_name) { ASSERT_NO_FATAL_FAILURE(method_name()); } \
     TEST_P(AudioStreamOut, method_name) { ASSERT_NO_FATAL_FAILURE(method_name()); }
@@ -1650,10 +1519,8 @@
     args.sourceMetadata = GenerateSourceMetadata(portConfig.value());
     args.bufferSizeFrames = kDefaultBufferSizeFrames;
     aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
-    ScopedAStatus status = module->openOutputStream(args, &ret);
-    EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-            << status
-            << " returned when no offload info is provided for a compressed offload mix port";
+    EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openOutputStream(args, &ret))
+            << "when no offload info is provided for a compressed offload mix port";
 }
 
 // Tests specific to audio patches. The fixure class is named 'AudioModulePatch'
@@ -1674,9 +1541,8 @@
         AudioPatch patch;
         patch.sourcePortConfigIds = sources;
         patch.sinkPortConfigIds = sinks;
-        ScopedAStatus status = module->setAudioPatch(patch, &patch);
-        ASSERT_EQ(expectedException, status.getExceptionCode())
-                << status << ": patch source ids: " << android::internal::ToString(sources)
+        ASSERT_STATUS(expectedException, module->setAudioPatch(patch, &patch))
+                << "patch source ids: " << android::internal::ToString(sources)
                 << "; sink ids: " << android::internal::ToString(sinks);
     }
 
@@ -1694,9 +1560,8 @@
                                           patch.get().sinkPortConfigIds.begin(),
                                           patch.get().sinkPortConfigIds.end());
         for (const auto portConfigId : sourceAndSinkPortConfigIds) {
-            ScopedAStatus status = module->resetAudioPortConfig(portConfigId);
-            EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
-                    << status << " returned for port config ID " << portConfigId;
+            EXPECT_STATUS(EX_ILLEGAL_STATE, module->resetAudioPortConfig(portConfigId))
+                    << "port config ID " << portConfigId;
         }
     }
 
@@ -1741,10 +1606,8 @@
         }
         WithAudioPatch patch(srcSinkPair.value().first, srcSinkPair.value().second);
         ASSERT_NO_FATAL_FAILURE(patch.SetUpPortConfigs(module.get()));
-        ScopedAStatus status = patch.SetUpNoChecks(module.get());
-        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << ": when setting up a patch from "
-                << srcSinkPair.value().first.toString() << " to "
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, patch.SetUpNoChecks(module.get()))
+                << "when setting up a patch from " << srcSinkPair.value().first.toString() << " to "
                 << srcSinkPair.value().second.toString() << " that does not have a route";
     }
 
@@ -1800,10 +1663,9 @@
         for (const auto patchId : GetNonExistentIds(patchIds)) {
             AudioPatch patchWithNonExistendId = patch.get();
             patchWithNonExistendId.id = patchId;
-            ScopedAStatus status =
-                    module->setAudioPatch(patchWithNonExistendId, &patchWithNonExistendId);
-            EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                    << status << " returned for patch ID " << patchId;
+            EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+                          module->setAudioPatch(patchWithNonExistendId, &patchWithNonExistendId))
+                    << "patch ID " << patchId;
         }
     }
 };
@@ -1825,9 +1687,8 @@
     std::set<int32_t> patchIds;
     ASSERT_NO_FATAL_FAILURE(GetAllPatchIds(&patchIds));
     for (const auto patchId : GetNonExistentIds(patchIds)) {
-        ScopedAStatus status = module->resetAudioPatch(patchId);
-        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
-                << status << " returned for patch ID " << patchId;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->resetAudioPatch(patchId))
+                << "patch ID " << patchId;
     }
 }
 
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index f70948c..9b100b1 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -14,7 +14,11 @@
  * limitations under the License.
  */
 
+#include <memory>
 #include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
 
 #define LOG_TAG "VtsHalAudioEffect"
 
@@ -35,37 +39,88 @@
 using ndk::ScopedAStatus;
 
 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;
 
-namespace ndk {
-std::ostream& operator<<(std::ostream& str, const ScopedAStatus& status) {
-    str << status.getDescription();
-    return str;
-}
-}  // namespace ndk
-
-class EffectFactory : public testing::TestWithParam<std::string> {
+class EffectFactoryHelper {
   public:
-    void SetUp() override { ASSERT_NO_FATAL_FAILURE(ConnectToService()); }
+    EffectFactoryHelper(const std::string& name) : mServiceName(name) {}
 
-    void TearDown() override {}
-
-    void ConnectToService() {
-        serviceName = GetParam();
-        factory = IFactory::fromBinder(binderUtil.connectToService(serviceName));
-        ASSERT_NE(factory, nullptr);
+    void ConnectToFactoryService() {
+        mEffectFactory = IFactory::fromBinder(binderUtil.connectToService(mServiceName));
+        ASSERT_NE(mEffectFactory, nullptr);
     }
 
-    void RestartService() {
-        ASSERT_NE(factory, nullptr);
-        factory = IFactory::fromBinder(binderUtil.restartService());
-        ASSERT_NE(factory, nullptr);
+    void RestartFactoryService() {
+        ASSERT_NE(mEffectFactory, nullptr);
+        mEffectFactory = IFactory::fromBinder(binderUtil.restartService());
+        ASSERT_NE(mEffectFactory, nullptr);
     }
 
-    std::shared_ptr<IFactory> factory;
-    std::string serviceName;
+    void QueryAllEffects() {
+        EXPECT_NE(mEffectFactory, nullptr);
+        ScopedAStatus status =
+                mEffectFactory->queryEffects(std::nullopt, std::nullopt, &mCompleteIds);
+        EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+    }
+
+    void QueryEffects(const std::optional<AudioUuid>& in_type,
+                      const std::optional<AudioUuid>& in_instance,
+                      std::vector<Descriptor::Identity>* _aidl_return) {
+        EXPECT_NE(mEffectFactory, nullptr);
+        ScopedAStatus status = mEffectFactory->queryEffects(in_type, in_instance, _aidl_return);
+        EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+        mIds = *_aidl_return;
+    }
+
+    void CreateEffects() {
+        EXPECT_NE(mEffectFactory, nullptr);
+        ScopedAStatus status;
+        for (const auto& id : mIds) {
+            std::shared_ptr<IEffect> effect;
+            status = mEffectFactory->createEffect(id.uuid, &effect);
+            EXPECT_EQ(status.getExceptionCode(), EX_NONE) << id.toString();
+            EXPECT_NE(effect, nullptr) << id.toString();
+            mEffectIdMap[effect] = id;
+        }
+    }
+
+    void DestroyEffects() {
+        EXPECT_NE(mEffectFactory, nullptr);
+        ScopedAStatus status;
+        for (const auto& it : mEffectIdMap) {
+            status = mEffectFactory->destroyEffect(it.first);
+            EXPECT_EQ(status.getExceptionCode(), EX_NONE) << it.second.toString();
+        }
+        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),
@@ -77,25 +132,23 @@
             static_cast<int32_t>(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
 };
 
-TEST_P(EffectFactory, SetupAndTearDown) {
+TEST_P(EffectFactoryTest, SetupAndTearDown) {
     // Intentionally empty test body.
 }
 
-TEST_P(EffectFactory, CanBeRestarted) {
-    ASSERT_NO_FATAL_FAILURE(RestartService());
+TEST_P(EffectFactoryTest, CanBeRestarted) {
+    ASSERT_NO_FATAL_FAILURE(mFactory.RestartFactoryService());
 }
 
-TEST_P(EffectFactory, QueriedDescriptorList) {
+TEST_P(EffectFactoryTest, QueriedDescriptorList) {
     std::vector<Descriptor::Identity> descriptors;
-    ScopedAStatus status = factory->queryEffects(std::nullopt, std::nullopt, &descriptors);
-    EXPECT_EQ(EX_NONE, status.getExceptionCode());
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
     EXPECT_NE(static_cast<int>(descriptors.size()), 0);
 }
 
-TEST_P(EffectFactory, DescriptorUUIDNotNull) {
+TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) {
     std::vector<Descriptor::Identity> descriptors;
-    ScopedAStatus status = factory->queryEffects(std::nullopt, std::nullopt, &descriptors);
-    EXPECT_EQ(EX_NONE, status.getExceptionCode());
+    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);
@@ -103,28 +156,176 @@
     }
 }
 
-TEST_P(EffectFactory, QueriedDescriptorNotExistType) {
+TEST_P(EffectFactoryTest, QueriedDescriptorNotExistType) {
     std::vector<Descriptor::Identity> descriptors;
-    ScopedAStatus status = factory->queryEffects(nullUuid, std::nullopt, &descriptors);
-    EXPECT_EQ(EX_NONE, status.getExceptionCode());
+    mFactory.QueryEffects(nullUuid, std::nullopt, &descriptors);
     EXPECT_EQ(static_cast<int>(descriptors.size()), 0);
 }
 
-TEST_P(EffectFactory, QueriedDescriptorNotExistInstance) {
+TEST_P(EffectFactoryTest, QueriedDescriptorNotExistInstance) {
     std::vector<Descriptor::Identity> descriptors;
-    ScopedAStatus status = factory->queryEffects(std::nullopt, nullUuid, &descriptors);
-    EXPECT_EQ(EX_NONE, status.getExceptionCode());
+    mFactory.QueryEffects(std::nullopt, nullUuid, &descriptors);
     EXPECT_EQ(static_cast<int>(descriptors.size()), 0);
 }
 
-INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactory,
+TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    int numIds = static_cast<int>(mFactory.GetEffectIds().size());
+    EXPECT_NE(numIds, 0);
+
+    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+    mFactory.CreateEffects();
+    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), numIds);
+    mFactory.DestroyEffects();
+    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+
+    // Create and destroy again
+    mFactory.CreateEffects();
+    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), numIds);
+    mFactory.DestroyEffects();
+    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+}
+
+TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    int numIds = static_cast<int>(mFactory.GetEffectIds().size());
+    EXPECT_NE(numIds, 0);
+
+    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+    mFactory.CreateEffects();
+    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), numIds);
+    // Create effect instances of same implementation
+    mFactory.CreateEffects();
+    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 2 * numIds);
+
+    mFactory.CreateEffects();
+    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 3 * numIds);
+
+    mFactory.DestroyEffects();
+    EXPECT_EQ(static_cast<int>(mFactory.GetEffectMap().size()), 0);
+}
+
+INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactoryTest,
                          testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
                          android::PrintInstanceNameToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EffectFactory);
+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());
+    }
+
+    void TearDown() override {
+        CloseEffects();
+        ASSERT_NO_FATAL_FAILURE(mFactory.DestroyEffects());
+    }
+
+    void OpenEffects() {
+        auto open = [](const std::shared_ptr<IEffect>& effect) {
+            ScopedAStatus status = effect->open();
+            EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(open));
+    }
+
+    void CloseEffects() {
+        auto close = [](const std::shared_ptr<IEffect>& effect) {
+            ScopedAStatus status = effect->close();
+            EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
+    }
+
+    void GetEffectDescriptors() {
+        auto get = [](const std::shared_ptr<IEffect>& effect) {
+            Descriptor desc;
+            ScopedAStatus status = effect->getDescriptor(&desc);
+            EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
+    }
+
+    template <typename Functor>
+    void ForEachEffect(Functor functor) {
+        auto effectMap = mFactory.GetEffectMap();
+        ScopedAStatus status;
+        for (const auto& it : effectMap) {
+            SCOPED_TRACE(it.second.toString());
+            functor(it.first);
+        }
+    }
+
+    EffectFactoryHelper mFactory = EffectFactoryHelper(GetParam());
+};
+
+TEST_P(AudioEffect, OpenEffectTest) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+}
+
+TEST_P(AudioEffect, OpenAndCloseEffect) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+TEST_P(AudioEffect, CloseUnopenedEffectTest) {
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+TEST_P(AudioEffect, DoubleOpenCloseEffects) {
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+
+    EXPECT_NO_FATAL_FAILURE(OpenEffects());
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+    EXPECT_NO_FATAL_FAILURE(CloseEffects());
+}
+
+TEST_P(AudioEffect, GetDescriptors) {
+    EXPECT_NO_FATAL_FAILURE(GetEffectDescriptors());
+}
+
+TEST_P(AudioEffect, DescriptorIdExistAndUnique) {
+    auto checker = [&](const std::shared_ptr<IEffect>& effect) {
+        Descriptor desc;
+        std::vector<Descriptor::Identity> idList;
+        ScopedAStatus status = effect->getDescriptor(&desc);
+        EXPECT_EQ(status.getExceptionCode(), EX_NONE);
+        mFactory.QueryEffects(desc.common.id.type, desc.common.id.uuid, &idList);
+        EXPECT_EQ(static_cast<int>(idList.size()), 1);
+    };
+    EXPECT_NO_FATAL_FAILURE(ForEachEffect(checker));
+
+    // Check unique with a set
+    auto stringHash = [](const Descriptor::Identity& id) {
+        return std::hash<std::string>()(id.toString());
+    };
+    auto vec = mFactory.GetCompleteEffectIdList();
+    std::unordered_set<Descriptor::Identity, decltype(stringHash)> idSet(0, stringHash);
+    for (auto it : vec) {
+        EXPECT_EQ(static_cast<int>(idSet.count(it)), 0);
+        idSet.insert(it);
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(AudioEffectTest, AudioEffect,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffect);
 
 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/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
index 33a57d3..0c949d6 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
+++ b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
@@ -136,6 +136,66 @@
             ]
         },
         {
+            "property": "VehicleProperty::SEAT_MEMORY_SELECT",
+            "defaultValue": {
+                "int32Values": [
+                    1
+                ]
+            },
+            "areas": [
+                {
+                    "areaId": "Constants::SEAT_1_LEFT",
+                    "minInt32Value": 0,
+                    "maxInt32Value": 3
+                },
+                {
+                    "areaId": "Constants::SEAT_1_RIGHT",
+                    "minInt32Value": 0,
+                    "maxInt32Value": 3
+                },
+                {
+                    "areaId": "Constants::SEAT_2_LEFT",
+                    "minInt32Value": 0,
+                    "maxInt32Value": 3
+                },
+                {
+                    "areaId": "Constants::SEAT_2_RIGHT",
+                    "minInt32Value": 0,
+                    "maxInt32Value": 3
+                }
+            ]
+        },
+        {
+            "property": "VehicleProperty::SEAT_MEMORY_SET",
+            "defaultValue": {
+                "int32Values": [
+                    1
+                ]
+            },
+            "areas": [
+                {
+                    "areaId": "Constants::SEAT_1_LEFT",
+                    "minInt32Value": 0,
+                    "maxInt32Value": 3
+                },
+                {
+                    "areaId": "Constants::SEAT_1_RIGHT",
+                    "minInt32Value": 0,
+                    "maxInt32Value": 3
+                },
+                {
+                    "areaId": "Constants::SEAT_2_LEFT",
+                    "minInt32Value": 0,
+                    "maxInt32Value": 3
+                },
+                {
+                    "areaId": "Constants::SEAT_2_RIGHT",
+                    "minInt32Value": 0,
+                    "maxInt32Value": 3
+                }
+            ]
+        },
+        {
             "property": "VehicleProperty::SEAT_BELT_BUCKLED",
             "defaultValue": {
                 "int32Values": [
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index 292d352..2b0caad 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -60,12 +60,14 @@
     LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
                << " MqDescriptor Invalid";
     audio_config_ = nullptr;
+    leaudio_connection_map_ = nullptr;
   } else {
     stack_iface_ = stack_iface;
     latency_modes_ = latency_modes;
     LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
               << ", AudioConfiguration=" << audio_config.toString();
     ReportSessionStatus();
+    is_streaming_ = false;
   }
 }
 
@@ -74,11 +76,13 @@
   bool toggled = IsSessionReady();
   LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
   audio_config_ = nullptr;
+  leaudio_connection_map_ = nullptr;
   stack_iface_ = nullptr;
   UpdateDataPath(nullptr);
   if (toggled) {
     ReportSessionStatus();
   }
+  is_streaming_ = false;
 }
 
 /***
@@ -106,18 +110,72 @@
   return *audio_config_;
 }
 
+const AudioConfiguration BluetoothAudioSession::GetLeAudioConnectionMap() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    return AudioConfiguration(LeAudioConfiguration{});
+  }
+  return *leaudio_connection_map_;
+}
+
 void BluetoothAudioSession::ReportAudioConfigChanged(
     const AudioConfiguration& audio_config) {
   if (session_type_ !=
           SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
       session_type_ !=
-          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
-      session_type_ !=
-          SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
     return;
   }
+
   std::lock_guard<std::recursive_mutex> guard(mutex_);
-  audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+  if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
+    LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
+               << toString(session_type_);
+    return;
+  }
+
+  if (is_streaming_) {
+    if (audio_config_ == nullptr) {
+      LOG(ERROR) << __func__ << " for SessionType=" << toString(session_type_)
+                 << " audio_config_ is nullptr during streaming. It shouldn't "
+                    "be happened";
+      return;
+    }
+
+    auto new_leaudio_config =
+        audio_config.get<AudioConfiguration::leAudioConfig>();
+    auto current_leaudio_config =
+        (*audio_config_).get<AudioConfiguration::leAudioConfig>();
+    if (new_leaudio_config.codecType != current_leaudio_config.codecType) {
+      LOG(ERROR)
+          << __func__ << " for SessionType=" << toString(session_type_)
+          << " codec type changed during streaming. It shouldn't be happened ";
+    }
+    auto new_lc3_config = new_leaudio_config.leAudioCodecConfig
+                              .get<LeAudioCodecConfiguration::lc3Config>();
+    auto current_lc3_config = current_leaudio_config.leAudioCodecConfig
+                                  .get<LeAudioCodecConfiguration::lc3Config>();
+    if ((new_lc3_config.pcmBitDepth != current_lc3_config.pcmBitDepth) ||
+        (new_lc3_config.samplingFrequencyHz !=
+         current_lc3_config.samplingFrequencyHz) ||
+        (new_lc3_config.frameDurationUs !=
+         current_lc3_config.frameDurationUs) ||
+        (new_lc3_config.octetsPerFrame != current_lc3_config.octetsPerFrame) ||
+        (new_lc3_config.blocksPerSdu != current_lc3_config.blocksPerSdu)) {
+      LOG(ERROR)
+          << __func__ << " for SessionType=" << toString(session_type_)
+          << " lc3 config changed during streaming. It shouldn't be happened";
+      return;
+    }
+
+    leaudio_connection_map_ =
+        std::make_unique<AudioConfiguration>(audio_config);
+  } else {
+    audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+    leaudio_connection_map_ =
+        std::make_unique<AudioConfiguration>(audio_config);
+  }
+
   if (observers_.empty()) {
     LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
                  << " has NO port state observer";
@@ -129,7 +187,11 @@
     LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_)
               << ", bluetooth_audio=0x"
               << ::android::base::StringPrintf("%04x", cookie);
-    if (cb->audio_configuration_changed_cb_ != nullptr) {
+    if (is_streaming_) {
+      if (cb->soft_audio_configuration_changed_cb_ != nullptr) {
+        cb->soft_audio_configuration_changed_cb_(cookie);
+      }
+    } else if (cb->audio_configuration_changed_cb_ != nullptr) {
       cb->audio_configuration_changed_cb_(cookie);
     }
   }
@@ -419,6 +481,12 @@
                  << " has NO port state observer";
     return;
   }
+  if (start_resp && status == BluetoothAudioStatus::SUCCESS) {
+    is_streaming_ = true;
+  } else if (!start_resp && (status == BluetoothAudioStatus::SUCCESS ||
+                             status == BluetoothAudioStatus::RECONFIGURATION)) {
+    is_streaming_ = false;
+  }
   for (auto& observer : observers_) {
     uint16_t cookie = observer.first;
     std::shared_ptr<PortStatusCallbacks> callback = observer.second;
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
index 5bf17bd..faf4ffb 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
@@ -102,6 +102,13 @@
    ***/
   std::function<void(uint16_t cookie, bool allowed)>
       low_latency_mode_allowed_cb_;
+  /***
+   * soft_audio_configuration_changed_cb_ - when the Bluetooth stack change
+   * the streamMap during the streaming, the BluetoothAudioProvider will invoke
+   * this callback to report to the bluetooth_audio module.
+   * @param: cookie - indicates which bluetooth_audio output should handle
+   ***/
+  std::function<void(uint16_t cookie)> soft_audio_configuration_changed_cb_;
 };
 
 class BluetoothAudioSession {
@@ -159,6 +166,12 @@
   const AudioConfiguration GetAudioConfig();
 
   /***
+   * The control function is for the bluetooth_audio module to get the current
+   * LE audio connection map
+   ***/
+  const AudioConfiguration GetLeAudioConnectionMap();
+
+  /***
    * The report function is used to report that the Bluetooth stack has notified
    * the audio configuration changed, and will invoke
    * audio_configuration_changed_cb_ to notify registered bluetooth_audio
@@ -206,8 +219,11 @@
   std::unique_ptr<DataMQ> data_mq_;
   // audio data configuration for both software and offloading
   std::unique_ptr<AudioConfiguration> audio_config_;
+  std::unique_ptr<AudioConfiguration> leaudio_connection_map_;
   std::vector<LatencyMode> latency_modes_;
   bool low_latency_allowed_ = true;
+  // saving those steaming state based on the session_type
+  bool is_streaming_ = false;
 
   // saving those registered bluetooth_audio's callbacks
   std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks>>
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
index 0782c82..881c6c1 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
@@ -95,6 +95,25 @@
   }
 
   /***
+   * The control API for the bluetooth_audio module to get current
+   * LE audio connection map
+   ***/
+  static const AudioConfiguration GetLeAudioConnectionMap(
+      const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if ((session_type ==
+             SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+         session_type ==
+             SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) &&
+        session_ptr != nullptr) {
+      return session_ptr->GetLeAudioConnectionMap();
+    }
+
+    return AudioConfiguration(LeAudioConfiguration{});
+  }
+
+  /***
    * Those control APIs for the bluetooth_audio module to start / suspend /
   stop
    * stream, to check position, and to update metadata.
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index d59def7..71243bf 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -16,7 +16,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <hal format="hidl" optional="true">
         <name>android.hardware.audio.effect</name>
         <version>6.0</version>
         <version>7.0</version>
@@ -37,7 +37,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="false">
+    <hal format="aidl" optional="true">
         <name>android.hardware.audio.effect</name>
         <version>1</version>
         <interface>
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
index db7e67d..5f0a176 100644
--- a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
@@ -259,19 +259,22 @@
 
         for (int i = 0; i < 3; i++) {
             const auto& plane = flex.planes[i];
-            // must have 8-bit depth
-            if (plane.bits_per_component != 8 || plane.bits_used != 8) {
+            // Must be a positive multiple of 8.
+            if (plane.bits_per_component <= 0 || (plane.bits_per_component % 8) != 0) {
                 return false;
             }
-
+            // Must be between 1 and bits_per_component, inclusive.
+            if (plane.bits_used < 1 || plane.bits_used > plane.bits_per_component) {
+                return false;
+            }
             if (plane.component == FLEX_COMPONENT_Y) {
                 // Y must not be interleaved
-                if (plane.h_increment != 1) {
+                if (plane.h_increment != 1 && plane.h_increment != 2) {
                     return false;
                 }
             } else {
                 // Cb and Cr can be interleaved
-                if (plane.h_increment != 1 && plane.h_increment != 2) {
+                if (plane.h_increment != 1 && plane.h_increment != 2 && plane.h_increment != 4) {
                     return false;
                 }
             }
diff --git a/power/OWNERS b/power/OWNERS
new file mode 100644
index 0000000..7229b22
--- /dev/null
+++ b/power/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 826709
+
+# ADPF virtual team
+lpy@google.com
+wvw@google.com