Merge changes I118b2c04,I111b72aa,Ia5d29126

* changes:
  audio: Add support for compressed offload
  audio: Improve debug logging in the AIDL version, fix bugs
  audio: Disable the C++ backend for android.hardware.audio.core
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index e964f2c..151da49 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -83,6 +83,10 @@
     ],
     stability: "vintf",
     backend: {
+        // The C++ backend is disabled transitively due to use of FMQ.
+        cpp: {
+            enabled: false,
+        },
         java: {
             platform_apis: true,
         },
diff --git a/audio/aidl/android/hardware/audio/core/IModule.aidl b/audio/aidl/android/hardware/audio/core/IModule.aidl
index f406cd8..802cb2f 100644
--- a/audio/aidl/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/android/hardware/audio/core/IModule.aidl
@@ -282,6 +282,8 @@
      * @throws EX_ILLEGAL_ARGUMENT In the following cases:
      *                             - If the port config can not be found by the ID.
      *                             - If the port config is not of an output mix port.
+     *                             - If the offload info is not provided for an offload
+     *                               port configuration.
      * @throws EX_ILLEGAL_STATE In the following cases:
      *                          - If the port config already has a stream opened on it.
      *                          - If the limit on the open stream count for the port has
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 4728a89..ad1d9c7 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -13,6 +13,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
+        "libstagefright_foundation",
         "android.media.audio.common.types-V1-ndk",
         "android.hardware.audio.core-V1-ndk",
     ],
@@ -37,6 +38,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
+        "libstagefright_foundation",
         "android.media.audio.common.types-V1-ndk",
         "android.hardware.audio.core-V1-ndk",
     ],
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index 19d0b3c..f5d679b 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -20,6 +20,7 @@
 #include <aidl/android/media/audio/common/AudioFormatType.h>
 #include <aidl/android/media/audio/common/AudioIoFlags.h>
 #include <aidl/android/media/audio/common/AudioOutputFlags.h>
+#include <media/stagefright/foundation/MediaDefs.h>
 
 #include "core-impl/Configuration.h"
 
@@ -42,16 +43,30 @@
 
 namespace aidl::android::hardware::audio::core::internal {
 
+static void fillProfile(AudioProfile* profile, const std::vector<int32_t>& channelLayouts,
+                        const std::vector<int32_t>& sampleRates) {
+    for (auto layout : channelLayouts) {
+        profile->channelMasks.push_back(
+                AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout));
+    }
+    profile->sampleRates.insert(profile->sampleRates.end(), sampleRates.begin(), sampleRates.end());
+}
+
 static AudioProfile createProfile(PcmType pcmType, const std::vector<int32_t>& channelLayouts,
                                   const std::vector<int32_t>& sampleRates) {
     AudioProfile profile;
     profile.format.type = AudioFormatType::PCM;
     profile.format.pcm = pcmType;
-    for (auto layout : channelLayouts) {
-        profile.channelMasks.push_back(
-                AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout));
-    }
-    profile.sampleRates.insert(profile.sampleRates.end(), sampleRates.begin(), sampleRates.end());
+    fillProfile(&profile, channelLayouts, sampleRates);
+    return profile;
+}
+
+static AudioProfile createProfile(const std::string& encodingType,
+                                  const std::vector<int32_t>& channelLayouts,
+                                  const std::vector<int32_t>& sampleRates) {
+    AudioProfile profile;
+    profile.format.encoding = encodingType;
+    fillProfile(&profile, channelLayouts, sampleRates);
     return profile;
 }
 
@@ -125,6 +140,8 @@
 //  * "primary output", PRIMARY, 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 44100, 48000
 //    - profile PCM 24-bit; MONO, STEREO; 44100, 48000
+//  * "compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active stream
+//    - profile MP3; MONO, STEREO; 44100, 48000
 //  * "loopback output", stream count unlimited
 //    - profile PCM 24-bit; STEREO; 48000
 //  * "primary input", 2 max open, 2 max active streams
@@ -136,8 +153,8 @@
 //    - profile PCM 24-bit; STEREO; 48000
 //
 // Routes:
-//  "primary out" -> "Null"
-//  "primary out" -> "USB Out"
+//  "primary out", "compressed offload" -> "Null"
+//  "primary out", "compressed offload" -> "USB Out"
 //  "loopback out" -> "Loopback Out"
 //  "Zero", "USB In" -> "primary input"
 //  "Loopback In" -> "loopback input"
@@ -183,6 +200,18 @@
                                       standardPcmAudioProfiles.end());
         c.ports.push_back(primaryOutMix);
 
+        AudioPort compressedOffloadOutMix =
+                createPort(c.nextPortId++, "compressed offload",
+                           1 << static_cast<int32_t>(AudioOutputFlags::DIRECT) |
+                                   1 << static_cast<int32_t>(AudioOutputFlags::COMPRESS_OFFLOAD) |
+                                   1 << static_cast<int32_t>(AudioOutputFlags::NON_BLOCKING),
+                           false, createPortMixExt(1, 1));
+        compressedOffloadOutMix.profiles.push_back(
+                createProfile(::android::MEDIA_MIMETYPE_AUDIO_MPEG,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+                              {44100, 48000}));
+        c.ports.push_back(compressedOffloadOutMix);
+
         AudioPort loopOutDevice = createPort(c.nextPortId++, "Loopback Out", 0, false,
                                              createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0));
         loopOutDevice.profiles.push_back(
@@ -244,8 +273,10 @@
         c.ports.push_back(usbInDevice);
         c.connectedProfiles[usbInDevice.id] = standardPcmAudioProfiles;
 
-        c.routes.push_back(createRoute({primaryOutMix.id}, nullOutDevice.id));
-        c.routes.push_back(createRoute({primaryOutMix.id}, usbOutDevice.id));
+        c.routes.push_back(
+                createRoute({primaryOutMix.id, compressedOffloadOutMix.id}, nullOutDevice.id));
+        c.routes.push_back(
+                createRoute({primaryOutMix.id, compressedOffloadOutMix.id}, usbOutDevice.id));
         c.routes.push_back(createRoute({loopOutMix.id}, loopOutDevice.id));
         c.routes.push_back(createRoute({zeroInDevice.id, usbInDevice.id}, primaryInMix.id));
         c.routes.push_back(createRoute({loopInDevice.id}, loopInMix.id));
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 961ee84..5b4d48a 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -405,6 +405,14 @@
                    << " does not correspond to an output mix port";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
+    if (portConfigIt->flags.has_value() &&
+        ((portConfigIt->flags.value().get<AudioIoFlags::Tag::output>() &
+          1 << static_cast<int32_t>(AudioOutputFlags::COMPRESS_OFFLOAD)) != 0) &&
+        !in_offloadInfo.has_value()) {
+        LOG(ERROR) << __func__ << ": port config id " << in_portConfigId
+                   << " has COMPRESS_OFFLOAD flag set, requires offload info";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
     if (mStreams.count(in_portConfigId) != 0) {
         LOG(ERROR) << __func__ << ": port config id " << in_portConfigId
                    << " already has a stream opened on it";
@@ -424,6 +432,7 @@
 }
 
 ndk::ScopedAStatus Module::setAudioPatch(const AudioPatch& in_requested, AudioPatch* _aidl_return) {
+    LOG(DEBUG) << __func__ << ": requested patch " << in_requested.toString();
     if (in_requested.sourcePortConfigIds.empty()) {
         LOG(ERROR) << __func__ << ": requested patch has empty sources list";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
diff --git a/audio/aidl/default/main.cpp b/audio/aidl/default/main.cpp
index 0de6047..aeb9983 100644
--- a/audio/aidl/default/main.cpp
+++ b/audio/aidl/default/main.cpp
@@ -25,20 +25,22 @@
 using aidl::android::hardware::audio::core::Module;
 
 int main() {
+    // This is a debug implementation, always enable debug logging.
+    android::base::SetMinimumLogSeverity(::android::base::DEBUG);
     ABinderProcess_setThreadPoolMaxThreadCount(16);
 
-    // make the default config service
+    // Make the default config service
     auto config = ndk::SharedRefBase::make<Config>();
     const std::string configName = std::string() + Config::descriptor + "/default";
     binder_status_t status =
             AServiceManager_addService(config->asBinder().get(), configName.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(STATUS_OK, status);
 
-    // make the default module
+    // Make the default module
     auto moduleDefault = ndk::SharedRefBase::make<Module>();
     const std::string moduleDefaultName = std::string() + Module::descriptor + "/default";
     status = AServiceManager_addService(moduleDefault->asBinder().get(), moduleDefaultName.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(STATUS_OK, status);
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index c160d1f..cd5915b 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -18,12 +18,12 @@
         "VtsHalAudioCoreTargetTest.cpp",
     ],
     shared_libs: [
-        "libbinder",
+        "libbinder_ndk",
     ],
     static_libs: [
-        "android.hardware.audio.common-V1-cpp",
-        "android.hardware.audio.core-V1-cpp",
-        "android.media.audio.common.types-V1-cpp",
+        "android.hardware.audio.common-V1-ndk",
+        "android.hardware.audio.core-V1-ndk",
+        "android.media.audio.common.types-V1-ndk",
     ],
     test_suites: [
         "general-tests",
diff --git a/audio/aidl/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
index 3f8d088..969b0e9 100644
--- a/audio/aidl/vts/ModuleConfig.cpp
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -15,25 +15,50 @@
  */
 
 #include <algorithm>
+#include <chrono>
 
-#include <android/media/audio/common/AudioIoFlags.h>
-#include <android/media/audio/common/AudioOutputFlags.h>
+#include <aidl/android/media/audio/common/AudioIoFlags.h>
+#include <aidl/android/media/audio/common/AudioOutputFlags.h>
 
 #include "ModuleConfig.h"
 
 using namespace android;
+using namespace std::chrono_literals;
 
-using android::hardware::audio::core::IModule;
-using android::media::audio::common::AudioChannelLayout;
-using android::media::audio::common::AudioFormatDescription;
-using android::media::audio::common::AudioFormatType;
-using android::media::audio::common::AudioIoFlags;
-using android::media::audio::common::AudioOutputFlags;
-using android::media::audio::common::AudioPort;
-using android::media::audio::common::AudioPortConfig;
-using android::media::audio::common::AudioPortExt;
-using android::media::audio::common::AudioProfile;
-using android::media::audio::common::Int;
+using aidl::android::hardware::audio::core::IModule;
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioEncapsulationMode;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::AudioOutputFlags;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioProfile;
+using aidl::android::media::audio::common::AudioUsage;
+using aidl::android::media::audio::common::Int;
+
+// static
+std::optional<AudioOffloadInfo> ModuleConfig::generateOffloadInfoIfNeeded(
+        const AudioPortConfig& portConfig) {
+    if (portConfig.flags.has_value() &&
+        portConfig.flags.value().getTag() == AudioIoFlags::Tag::output &&
+        (portConfig.flags.value().get<AudioIoFlags::Tag::output>() &
+         1 << static_cast<int>(AudioOutputFlags::COMPRESS_OFFLOAD)) != 0) {
+        AudioOffloadInfo offloadInfo;
+        offloadInfo.base.sampleRate = portConfig.sampleRate.value().value;
+        offloadInfo.base.channelMask = portConfig.channelMask.value();
+        offloadInfo.base.format = portConfig.format.value();
+        offloadInfo.bitRatePerSecond = 256;                                // Arbitrary value.
+        offloadInfo.durationUs = std::chrono::microseconds(1min).count();  // Arbitrary value.
+        offloadInfo.usage = AudioUsage::MEDIA;
+        offloadInfo.encapsulationMode = AudioEncapsulationMode::NONE;
+        return offloadInfo;
+    }
+    return {};
+}
 
 template <typename T>
 auto findById(const std::vector<T>& v, int32_t id) {
@@ -251,23 +276,23 @@
     std::string result;
     result.append("Ports: ");
     result.append(android::internal::ToString(mPorts));
-    result.append("Initial configs: ");
+    result.append("\nInitial configs: ");
     result.append(android::internal::ToString(mInitialConfigs));
-    result.append("Attached sink device ports: ");
+    result.append("\nAttached sink device ports: ");
     result.append(android::internal::ToString(mAttachedSinkDevicePorts));
-    result.append("Attached source device ports: ");
+    result.append("\nAttached source device ports: ");
     result.append(android::internal::ToString(mAttachedSourceDevicePorts));
-    result.append("External device ports: ");
+    result.append("\nExternal device ports: ");
     result.append(android::internal::ToString(mExternalDevicePorts));
-    result.append("Routes: ");
+    result.append("\nRoutes: ");
     result.append(android::internal::ToString(mRoutes));
     return result;
 }
 
-static std::vector<AudioPortConfig> combineAudioConfigs(const AudioPort& port,
-                                                        const AudioProfile& profile) {
-    std::vector<AudioPortConfig> configs;
-    configs.reserve(profile.channelMasks.size() * profile.sampleRates.size());
+static size_t combineAudioConfigs(const AudioPort& port, const AudioProfile& profile,
+                                  std::vector<AudioPortConfig>* result) {
+    const size_t newConfigCount = profile.channelMasks.size() * profile.sampleRates.size();
+    result->reserve(result->capacity() + newConfigCount);
     for (auto channelMask : profile.channelMasks) {
         for (auto sampleRate : profile.sampleRates) {
             AudioPortConfig config{};
@@ -277,66 +302,32 @@
             config.sampleRate = sr;
             config.channelMask = channelMask;
             config.format = profile.format;
+            config.flags = port.flags;
             config.ext = port.ext;
-            configs.push_back(config);
+            result->push_back(std::move(config));
         }
     }
-    return configs;
+    return newConfigCount;
 }
 
-std::vector<AudioPortConfig> ModuleConfig::generateInputAudioMixPortConfigs(
-        const std::vector<AudioPort>& ports, bool singleProfile) const {
+static bool isDynamicProfile(const AudioProfile& profile) {
+    return (profile.format.type == AudioFormatType::DEFAULT && profile.format.encoding.empty()) ||
+           profile.sampleRates.empty() || profile.channelMasks.empty();
+}
+
+std::vector<AudioPortConfig> ModuleConfig::generateAudioMixPortConfigs(
+        const std::vector<AudioPort>& ports, bool isInput, bool singleProfile) const {
     std::vector<AudioPortConfig> result;
     for (const auto& mixPort : ports) {
-        if (getAttachedSourceDevicesPortsForMixPort(mixPort).empty()) {
-            continue;  // no attached devices
+        if (getAttachedDevicesPortsForMixPort(isInput, mixPort).empty()) {
+            continue;
         }
         for (const auto& profile : mixPort.profiles) {
-            if (profile.format.type == AudioFormatType::DEFAULT || profile.sampleRates.empty() ||
-                profile.channelMasks.empty()) {
-                continue;  // dynamic profile
-            }
-            auto configs = combineAudioConfigs(mixPort, profile);
-            for (auto& config : configs) {
-                config.flags = mixPort.flags;
-                result.push_back(config);
-                if (singleProfile) return result;
-            }
-        }
-    }
-    return result;
-}
-
-static std::tuple<AudioIoFlags, bool> generateOutFlags(const AudioPort& mixPort) {
-    static const AudioIoFlags offloadFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(
-            (1 << static_cast<int>(AudioOutputFlags::COMPRESS_OFFLOAD)) |
-            (1 << static_cast<int>(AudioOutputFlags::DIRECT)));
-    const bool isOffload = (mixPort.flags.get<AudioIoFlags::Tag::output>() &
-                            (1 << static_cast<int>(AudioOutputFlags::COMPRESS_OFFLOAD))) != 0;
-    return {isOffload ? offloadFlags : mixPort.flags, isOffload};
-}
-
-std::vector<AudioPortConfig> ModuleConfig::generateOutputAudioMixPortConfigs(
-        const std::vector<AudioPort>& ports, bool singleProfile) const {
-    std::vector<AudioPortConfig> result;
-    for (const auto& mixPort : ports) {
-        if (getAttachedSinkDevicesPortsForMixPort(mixPort).empty()) {
-            continue;  // no attached devices
-        }
-        auto [flags, isOffload] = generateOutFlags(mixPort);
-        (void)isOffload;
-        for (const auto& profile : mixPort.profiles) {
-            if (profile.format.type == AudioFormatType::DEFAULT) continue;
-            auto configs = combineAudioConfigs(mixPort, profile);
-            for (auto& config : configs) {
-                // Some combinations of flags declared in the config file require special
-                // treatment.
-                // if (isOffload) {
-                //     config.offloadInfo.info(generateOffloadInfo(config.base));
-                // }
-                config.flags = flags;
-                result.push_back(config);
-                if (singleProfile) return result;
+            if (isDynamicProfile(profile)) continue;
+            combineAudioConfigs(mixPort, profile, &result);
+            if (singleProfile && !result.empty()) {
+                result.resize(1);
+                return result;
             }
         }
     }
@@ -349,9 +340,11 @@
     for (const auto& devicePort : ports) {
         const size_t resultSizeBefore = result.size();
         for (const auto& profile : devicePort.profiles) {
-            auto configs = combineAudioConfigs(devicePort, profile);
-            result.insert(result.end(), configs.begin(), configs.end());
-            if (singleProfile && !result.empty()) return result;
+            combineAudioConfigs(devicePort, profile, &result);
+            if (singleProfile && !result.empty()) {
+                result.resize(1);
+                return result;
+            }
         }
         if (resultSizeBefore == result.size()) {
             std::copy_if(mInitialConfigs.begin(), mInitialConfigs.end(), std::back_inserter(result),
diff --git a/audio/aidl/vts/ModuleConfig.h b/audio/aidl/vts/ModuleConfig.h
index 0e2738b..df13430 100644
--- a/audio/aidl/vts/ModuleConfig.h
+++ b/audio/aidl/vts/ModuleConfig.h
@@ -21,95 +21,94 @@
 #include <utility>
 #include <vector>
 
-#include <android/hardware/audio/core/AudioRoute.h>
-#include <android/hardware/audio/core/IModule.h>
-#include <android/media/audio/common/AudioPort.h>
-#include <binder/Status.h>
+#include <aidl/android/hardware/audio/core/AudioRoute.h>
+#include <aidl/android/hardware/audio/core/IModule.h>
+#include <aidl/android/media/audio/common/AudioOffloadInfo.h>
+#include <aidl/android/media/audio/common/AudioPort.h>
 
 class ModuleConfig {
   public:
-    using SrcSinkPair = std::pair<android::media::audio::common::AudioPortConfig,
-                                  android::media::audio::common::AudioPortConfig>;
+    using SrcSinkPair = std::pair<aidl::android::media::audio::common::AudioPortConfig,
+                                  aidl::android::media::audio::common::AudioPortConfig>;
     using SrcSinkGroup =
-            std::pair<android::hardware::audio::core::AudioRoute, std::vector<SrcSinkPair>>;
+            std::pair<aidl::android::hardware::audio::core::AudioRoute, std::vector<SrcSinkPair>>;
 
-    explicit ModuleConfig(android::hardware::audio::core::IModule* module);
-    android::binder::Status getStatus() const { return mStatus; }
-    std::string getError() const { return mStatus.toString8().c_str(); }
+    static std::optional<aidl::android::media::audio::common::AudioOffloadInfo>
+    generateOffloadInfoIfNeeded(
+            const aidl::android::media::audio::common::AudioPortConfig& portConfig);
 
-    std::vector<android::media::audio::common::AudioPort> getAttachedDevicePorts() const;
-    std::vector<android::media::audio::common::AudioPort> getExternalDevicePorts() const;
-    std::vector<android::media::audio::common::AudioPort> getInputMixPorts() const;
-    std::vector<android::media::audio::common::AudioPort> getOutputMixPorts() const;
-    std::vector<android::media::audio::common::AudioPort> getMixPorts(bool isInput) const {
+    explicit ModuleConfig(aidl::android::hardware::audio::core::IModule* module);
+    const ndk::ScopedAStatus& getStatus() const { return mStatus; }
+    std::string getError() const { return mStatus.getMessage(); }
+
+    std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicePorts() const;
+    std::vector<aidl::android::media::audio::common::AudioPort> getExternalDevicePorts() const;
+    std::vector<aidl::android::media::audio::common::AudioPort> getInputMixPorts() const;
+    std::vector<aidl::android::media::audio::common::AudioPort> getOutputMixPorts() const;
+    std::vector<aidl::android::media::audio::common::AudioPort> getMixPorts(bool isInput) const {
         return isInput ? getInputMixPorts() : getOutputMixPorts();
     }
 
-    std::vector<android::media::audio::common::AudioPort> getAttachedDevicesPortsForMixPort(
-            bool isInput, const android::media::audio::common::AudioPort& mixPort) const {
+    std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicesPortsForMixPort(
+            bool isInput, const aidl::android::media::audio::common::AudioPort& mixPort) const {
         return isInput ? getAttachedSourceDevicesPortsForMixPort(mixPort)
                        : getAttachedSinkDevicesPortsForMixPort(mixPort);
     }
-    std::vector<android::media::audio::common::AudioPort> getAttachedSinkDevicesPortsForMixPort(
-            const android::media::audio::common::AudioPort& mixPort) const;
-    std::vector<android::media::audio::common::AudioPort> getAttachedSourceDevicesPortsForMixPort(
-            const android::media::audio::common::AudioPort& mixPort) const;
-    std::optional<android::media::audio::common::AudioPort> getSourceMixPortForAttachedDevice()
-            const;
+    std::vector<aidl::android::media::audio::common::AudioPort>
+    getAttachedSinkDevicesPortsForMixPort(
+            const aidl::android::media::audio::common::AudioPort& mixPort) const;
+    std::vector<aidl::android::media::audio::common::AudioPort>
+    getAttachedSourceDevicesPortsForMixPort(
+            const aidl::android::media::audio::common::AudioPort& mixPort) const;
+    std::optional<aidl::android::media::audio::common::AudioPort>
+    getSourceMixPortForAttachedDevice() const;
 
     std::optional<SrcSinkPair> getNonRoutableSrcSinkPair(bool isInput) const;
     std::optional<SrcSinkPair> getRoutableSrcSinkPair(bool isInput) const;
     std::vector<SrcSinkGroup> getRoutableSrcSinkGroups(bool isInput) const;
 
-    std::vector<android::media::audio::common::AudioPortConfig>
+    std::vector<aidl::android::media::audio::common::AudioPortConfig>
     getPortConfigsForAttachedDevicePorts() const {
         return generateAudioDevicePortConfigs(getAttachedDevicePorts(), false);
     }
-    std::vector<android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts() const {
-        auto inputs = generateInputAudioMixPortConfigs(getInputMixPorts(), false);
-        auto outputs = generateOutputAudioMixPortConfigs(getOutputMixPorts(), false);
+    std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts()
+            const {
+        auto inputs = generateAudioMixPortConfigs(getInputMixPorts(), true, false);
+        auto outputs = generateAudioMixPortConfigs(getOutputMixPorts(), false, false);
         inputs.insert(inputs.end(), outputs.begin(), outputs.end());
         return inputs;
     }
-    std::vector<android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
+    std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
             bool isInput) const {
-        return isInput ? generateInputAudioMixPortConfigs(getInputMixPorts(), false)
-                       : generateOutputAudioMixPortConfigs(getOutputMixPorts(), false);
+        return generateAudioMixPortConfigs(getMixPorts(isInput), isInput, false);
     }
-    std::vector<android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
-            bool isInput, const android::media::audio::common::AudioPort& port) const {
-        return isInput ? generateInputAudioMixPortConfigs({port}, false)
-                       : generateOutputAudioMixPortConfigs({port}, false);
+    std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
+            bool isInput, const aidl::android::media::audio::common::AudioPort& port) const {
+        return generateAudioMixPortConfigs({port}, isInput, false);
     }
-    std::optional<android::media::audio::common::AudioPortConfig> getSingleConfigForMixPort(
+    std::optional<aidl::android::media::audio::common::AudioPortConfig> getSingleConfigForMixPort(
             bool isInput) const {
-        const auto config = isInput ? generateInputAudioMixPortConfigs(getInputMixPorts(), true)
-                                    : generateOutputAudioMixPortConfigs(getOutputMixPorts(), true);
-        // TODO: Avoid returning configs for offload since they require an extra
-        //       argument to openOutputStream.
+        const auto config = generateAudioMixPortConfigs(getMixPorts(isInput), isInput, true);
         if (!config.empty()) {
             return *config.begin();
-        } else {
-            return {};
         }
+        return {};
     }
-    std::optional<android::media::audio::common::AudioPortConfig> getSingleConfigForMixPort(
-            bool isInput, const android::media::audio::common::AudioPort& port) const {
-        const auto config = isInput ? generateInputAudioMixPortConfigs({port}, true)
-                                    : generateOutputAudioMixPortConfigs({port}, true);
+    std::optional<aidl::android::media::audio::common::AudioPortConfig> getSingleConfigForMixPort(
+            bool isInput, const aidl::android::media::audio::common::AudioPort& port) const {
+        const auto config = generateAudioMixPortConfigs({port}, isInput, true);
         if (!config.empty()) {
             return *config.begin();
-        } else {
-            return {};
         }
+        return {};
     }
 
-    std::vector<android::media::audio::common::AudioPortConfig> getPortConfigsForDevicePort(
-            const android::media::audio::common::AudioPort& port) const {
+    std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForDevicePort(
+            const aidl::android::media::audio::common::AudioPort& port) const {
         return generateAudioDevicePortConfigs({port}, false);
     }
-    android::media::audio::common::AudioPortConfig getSingleConfigForDevicePort(
-            const android::media::audio::common::AudioPort& port) const {
+    aidl::android::media::audio::common::AudioPortConfig getSingleConfigForDevicePort(
+            const aidl::android::media::audio::common::AudioPort& port) const {
         const auto config = generateAudioDevicePortConfigs({port}, true);
         return *config.begin();
     }
@@ -117,26 +116,24 @@
     std::string toString() const;
 
   private:
-    std::vector<android::media::audio::common::AudioPortConfig> generateInputAudioMixPortConfigs(
-            const std::vector<android::media::audio::common::AudioPort>& ports,
-            bool singleProfile) const;
-    std::vector<android::media::audio::common::AudioPortConfig> generateOutputAudioMixPortConfigs(
-            const std::vector<android::media::audio::common::AudioPort>& ports,
+    std::vector<aidl::android::media::audio::common::AudioPortConfig> generateAudioMixPortConfigs(
+            const std::vector<aidl::android::media::audio::common::AudioPort>& ports, bool isInput,
             bool singleProfile) const;
 
     // Unlike MixPorts, the generator for DevicePorts always returns a non-empty
     // vector for a non-empty input port list. If there are no profiles in the
     // port, its initial configs are looked up, if there are none,
     // then an empty config is used, assuming further negotiation via setAudioPortConfig.
-    std::vector<android::media::audio::common::AudioPortConfig> generateAudioDevicePortConfigs(
-            const std::vector<android::media::audio::common::AudioPort>& ports,
+    std::vector<aidl::android::media::audio::common::AudioPortConfig>
+    generateAudioDevicePortConfigs(
+            const std::vector<aidl::android::media::audio::common::AudioPort>& ports,
             bool singleProfile) const;
 
-    android::binder::Status mStatus = android::binder::Status::ok();
-    std::vector<android::media::audio::common::AudioPort> mPorts;
-    std::vector<android::media::audio::common::AudioPortConfig> mInitialConfigs;
+    ndk::ScopedAStatus mStatus = ndk::ScopedAStatus::ok();
+    std::vector<aidl::android::media::audio::common::AudioPort> mPorts;
+    std::vector<aidl::android::media::audio::common::AudioPortConfig> mInitialConfigs;
     std::set<int32_t> mAttachedSinkDevicePorts;
     std::set<int32_t> mAttachedSourceDevicePorts;
     std::set<int32_t> mExternalDevicePorts;
-    std::vector<android::hardware::audio::core::AudioRoute> mRoutes;
+    std::vector<aidl::android::hardware::audio::core::AudioRoute> mRoutes;
 };
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
index 824ac8d..bb24365 100644
--- a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
@@ -27,41 +27,48 @@
 
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
+#include <aidl/android/hardware/audio/core/IConfig.h>
+#include <aidl/android/hardware/audio/core/IModule.h>
+#include <aidl/android/media/audio/common/AudioIoFlags.h>
+#include <aidl/android/media/audio/common/AudioOutputFlags.h>
 #include <android-base/properties.h>
-#include <android/hardware/audio/core/IConfig.h>
-#include <android/hardware/audio/core/IModule.h>
-#include <android/media/audio/common/AudioIoFlags.h>
-#include <android/media/audio/common/AudioOutputFlags.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
 
 #include "ModuleConfig.h"
 
 using namespace android;
-using android::binder::Status;
-using android::hardware::audio::common::PlaybackTrackMetadata;
-using android::hardware::audio::common::RecordTrackMetadata;
-using android::hardware::audio::common::SinkMetadata;
-using android::hardware::audio::common::SourceMetadata;
-using android::hardware::audio::core::AudioPatch;
-using android::hardware::audio::core::AudioRoute;
-using android::hardware::audio::core::IModule;
-using android::hardware::audio::core::IStreamIn;
-using android::hardware::audio::core::IStreamOut;
-using android::hardware::audio::core::ModuleDebug;
-using android::media::audio::common::AudioContentType;
-using android::media::audio::common::AudioDevice;
-using android::media::audio::common::AudioDeviceAddress;
-using android::media::audio::common::AudioDeviceType;
-using android::media::audio::common::AudioFormatType;
-using android::media::audio::common::AudioIoFlags;
-using android::media::audio::common::AudioOutputFlags;
-using android::media::audio::common::AudioPort;
-using android::media::audio::common::AudioPortConfig;
-using android::media::audio::common::AudioPortDeviceExt;
-using android::media::audio::common::AudioPortExt;
-using android::media::audio::common::AudioSource;
-using android::media::audio::common::AudioUsage;
+using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
+using aidl::android::hardware::audio::common::RecordTrackMetadata;
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::hardware::audio::core::AudioPatch;
+using aidl::android::hardware::audio::core::AudioRoute;
+using aidl::android::hardware::audio::core::IModule;
+using aidl::android::hardware::audio::core::IStreamIn;
+using aidl::android::hardware::audio::core::IStreamOut;
+using aidl::android::hardware::audio::core::ModuleDebug;
+using aidl::android::media::audio::common::AudioContentType;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioOutputFlags;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::AudioPortDeviceExt;
+using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::AudioUsage;
+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) {
@@ -85,16 +92,23 @@
     return AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(std::to_string(++nextId));
 }
 
-struct AidlDeathRecipient : IBinder::DeathRecipient {
+struct AidlDeathRecipient {
+    const ndk::SpAIBinder binder;
+    const ndk::ScopedAIBinder_DeathRecipient recipient;
     std::mutex mutex;
     std::condition_variable condition;
     bool fired = false;
-    wp<IBinder> who;
 
-    void binderDied(const wp<IBinder>& who) override {
+    explicit AidlDeathRecipient(const ndk::SpAIBinder& binder)
+        : binder(binder), recipient(AIBinder_DeathRecipient_new(&binderDiedCallbackAidl)) {}
+
+    binder_status_t linkToDeath() {
+        return AIBinder_linkToDeath(binder.get(), recipient.get(), this);
+    }
+
+    void binderDied() {
         std::unique_lock<std::mutex> lock(mutex);
         fired = true;
-        this->who = who;
         condition.notify_one();
     };
 
@@ -103,6 +117,11 @@
         condition.wait_for(lock, std::chrono::milliseconds(timeoutMs), [this]() { return fired; });
         return fired;
     }
+
+    static void binderDiedCallbackAidl(void* cookie) {
+        AidlDeathRecipient* self = static_cast<AidlDeathRecipient*>(cookie);
+        self->binderDied();
+    }
 };
 
 template <typename T>
@@ -119,21 +138,27 @@
     return false;
 }
 
+// All 'With*' classes are move-only because they are associated with some
+// resource or state of a HAL module.
 class WithDebugFlags {
   public:
+    static WithDebugFlags createNested(const WithDebugFlags& parent) {
+        return WithDebugFlags(parent.mFlags);
+    }
+
     WithDebugFlags() {}
     explicit WithDebugFlags(const ModuleDebug& initial) : mInitial(initial), mFlags(initial) {}
-    explicit WithDebugFlags(const WithDebugFlags& initial)
-        : mInitial(initial.mFlags), mFlags(initial.mFlags) {}
+    WithDebugFlags(const WithDebugFlags&) = delete;
+    WithDebugFlags& operator=(const WithDebugFlags&) = delete;
     ~WithDebugFlags() {
         if (mModule != nullptr) {
-            Status status = mModule->setModuleDebug(mInitial);
-            EXPECT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+            ScopedAStatus status = mModule->setModuleDebug(mInitial);
+            EXPECT_EQ(EX_NONE, status.getExceptionCode()) << status;
         }
     }
     void SetUp(IModule* module) {
-        Status status = module->setModuleDebug(mFlags);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->setModuleDebug(mFlags);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     ModuleDebug& flags() { return mFlags; }
 
@@ -151,10 +176,12 @@
   public:
     WithAudioPortConfig() {}
     explicit WithAudioPortConfig(const AudioPortConfig& config) : mInitialConfig(config) {}
+    WithAudioPortConfig(const WithAudioPortConfig&) = delete;
+    WithAudioPortConfig& operator=(const WithAudioPortConfig&) = delete;
     ~WithAudioPortConfig() {
         if (mModule != nullptr) {
-            Status status = mModule->resetAudioPortConfig(getId());
-            EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
+            ScopedAStatus status = mModule->resetAudioPortConfig(getId());
+            EXPECT_EQ(EX_NONE, status.getExceptionCode())
                     << status << "; port config id " << getId();
         }
     }
@@ -174,8 +201,8 @@
         if (mInitialConfig.id == 0) {
             AudioPortConfig suggested;
             bool applied = false;
-            Status status = module->setAudioPortConfig(mInitialConfig, &suggested, &applied);
-            ASSERT_EQ(Status::EX_NONE, status.exceptionCode())
+            ScopedAStatus status = module->setAudioPortConfig(mInitialConfig, &suggested, &applied);
+            ASSERT_EQ(EX_NONE, status.getExceptionCode())
                     << status << "; Config: " << mInitialConfig.toString();
             if (!applied && negotiate) {
                 mInitialConfig = suggested;
@@ -206,25 +233,26 @@
 
     void TearDown() override {
         if (module != nullptr) {
-            Status status = module->setModuleDebug(ModuleDebug{});
-            EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
+            ScopedAStatus status = module->setModuleDebug(ModuleDebug{});
+            EXPECT_EQ(EX_NONE, status.getExceptionCode())
                     << status << " returned when resetting debug flags";
         }
     }
 
     void ConnectToService() {
-        module = android::waitForDeclaredService<IModule>(String16(GetParam().c_str()));
+        module = IModule::fromBinder(
+                ndk::SpAIBinder(AServiceManager_getService(GetParam().c_str())));
         ASSERT_NE(module, nullptr);
     }
 
     void RestartService() {
         ASSERT_NE(module, nullptr);
         moduleConfig.reset();
-        deathHandler = sp<AidlDeathRecipient>::make();
-        ASSERT_EQ(NO_ERROR, IModule::asBinder(module)->linkToDeath(deathHandler));
+        deathHandler.reset(new AidlDeathRecipient(module->asBinder()));
+        ASSERT_EQ(STATUS_OK, deathHandler->linkToDeath());
         ASSERT_TRUE(base::SetProperty("sys.audio.restart.hal", "1"));
         EXPECT_TRUE(deathHandler->waitForFired(3000));
-        deathHandler = nullptr;
+        deathHandler.reset();
         ASSERT_NO_FATAL_FAILURE(ConnectToService());
     }
 
@@ -235,8 +263,8 @@
             ASSERT_NO_FATAL_FAILURE(portConfig.SetUp(module.get()));  // calls setAudioPortConfig
             EXPECT_EQ(config.portId, portConfig.get().portId);
             std::vector<AudioPortConfig> retrievedPortConfigs;
-            Status status = module->getAudioPortConfigs(&retrievedPortConfigs);
-            ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+            ScopedAStatus status = module->getAudioPortConfigs(&retrievedPortConfigs);
+            ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
             const int32_t portConfigId = portConfig.getId();
             auto configIt = std::find_if(
                     retrievedPortConfigs.begin(), retrievedPortConfigs.end(),
@@ -256,12 +284,12 @@
 
     template <typename Entity>
     void GetAllEntityIds(std::set<int32_t>* entityIds,
-                         Status (IModule::*getter)(std::vector<Entity>*),
+                         ScopedAStatus (IModule::*getter)(std::vector<Entity>*),
                          const std::string& errorMessage) {
         std::vector<Entity> entities;
         {
-            Status status = (module.get()->*getter)(&entities);
-            ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+            ScopedAStatus status = (module.get()->*getter)(&entities);
+            ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
         }
         std::transform(entities.begin(), entities.end(),
                        std::inserter(*entityIds, entityIds->begin()),
@@ -290,13 +318,13 @@
     void SetUpModuleConfig() {
         if (moduleConfig == nullptr) {
             moduleConfig = std::make_unique<ModuleConfig>(module.get());
-            ASSERT_EQ(Status::EX_NONE, moduleConfig->getStatus().exceptionCode())
+            ASSERT_EQ(EX_NONE, moduleConfig->getStatus().getExceptionCode())
                     << "ModuleConfig init error: " << moduleConfig->getError();
         }
     }
 
-    sp<IModule> module;
-    sp<AidlDeathRecipient> deathHandler;
+    std::shared_ptr<IModule> module;
+    std::unique_ptr<AidlDeathRecipient> deathHandler;
     std::unique_ptr<ModuleConfig> moduleConfig;
     WithDebugFlags debug;
 };
@@ -306,16 +334,18 @@
     explicit WithDevicePortConnectedState(const AudioPort& idAndData) : mIdAndData(idAndData) {}
     WithDevicePortConnectedState(const AudioPort& id, const AudioDeviceAddress& address)
         : mIdAndData(setAudioPortAddress(id, address)) {}
+    WithDevicePortConnectedState(const WithDevicePortConnectedState&) = delete;
+    WithDevicePortConnectedState& operator=(const WithDevicePortConnectedState&) = delete;
     ~WithDevicePortConnectedState() {
         if (mModule != nullptr) {
-            Status status = mModule->disconnectExternalDevice(getId());
-            EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
+            ScopedAStatus status = mModule->disconnectExternalDevice(getId());
+            EXPECT_EQ(EX_NONE, status.getExceptionCode())
                     << status << " returned when disconnecting device port ID " << getId();
         }
     }
     void SetUp(IModule* module) {
-        Status status = module->connectExternalDevice(mIdAndData, &mConnectedPort);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode())
+        ScopedAStatus status = module->connectExternalDevice(mIdAndData, &mConnectedPort);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode())
                 << status << " returned when connecting device port ID & data "
                 << mIdAndData.toString();
         ASSERT_NE(mIdAndData.id, getId())
@@ -342,45 +372,54 @@
   public:
     WithStream() {}
     explicit WithStream(const AudioPortConfig& portConfig) : mPortConfig(portConfig) {}
+    WithStream(const WithStream&) = delete;
+    WithStream& operator=(const WithStream&) = delete;
     ~WithStream() {
         if (mStream != nullptr) {
-            Status status = mStream->close();
-            EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
+            ScopedAStatus status = mStream->close();
+            EXPECT_EQ(EX_NONE, status.getExceptionCode())
                     << status << "; port config id " << getPortId();
         }
     }
     void SetUpPortConfig(IModule* module) { ASSERT_NO_FATAL_FAILURE(mPortConfig.SetUp(module)); }
-    Status SetUpNoChecks(IModule* module) { return SetUpNoChecks(module, mPortConfig.get()); }
-    Status SetUpNoChecks(IModule* module, const AudioPortConfig& portConfig);
+    ScopedAStatus SetUpNoChecks(IModule* module) {
+        return SetUpNoChecks(module, mPortConfig.get());
+    }
+    ScopedAStatus SetUpNoChecks(IModule* module, const AudioPortConfig& portConfig);
     void SetUp(IModule* module) {
         ASSERT_NO_FATAL_FAILURE(SetUpPortConfig(module));
-        Status status = SetUpNoChecks(module);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode())
+        ScopedAStatus status = SetUpNoChecks(module);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode())
                 << status << "; port config id " << getPortId();
         ASSERT_NE(nullptr, mStream) << "; port config id " << getPortId();
     }
     Stream* get() const { return mStream.get(); }
+    std::shared_ptr<Stream> getSharedPointer() const { return mStream; }
     const AudioPortConfig& getPortConfig() const { return mPortConfig.get(); }
     int32_t getPortId() const { return mPortConfig.getId(); }
 
   private:
     WithAudioPortConfig mPortConfig;
-    sp<Stream> mStream;
+    std::shared_ptr<Stream> mStream;
 };
 
-template <>
-Status WithStream<IStreamIn>::SetUpNoChecks(IModule* module, const AudioPortConfig& portConfig) {
+SinkMetadata GenerateSinkMetadata(const AudioPortConfig& portConfig) {
     RecordTrackMetadata trackMeta;
     trackMeta.source = AudioSource::MIC;
     trackMeta.gain = 1.0;
     trackMeta.channelMask = portConfig.channelMask.value();
     SinkMetadata metadata;
     metadata.tracks.push_back(trackMeta);
-    return module->openInputStream(portConfig.id, metadata, &mStream);
+    return metadata;
 }
 
 template <>
-Status WithStream<IStreamOut>::SetUpNoChecks(IModule* module, const AudioPortConfig& portConfig) {
+ScopedAStatus WithStream<IStreamIn>::SetUpNoChecks(IModule* module,
+                                                   const AudioPortConfig& portConfig) {
+    return module->openInputStream(portConfig.id, GenerateSinkMetadata(portConfig), &mStream);
+}
+
+SourceMetadata GenerateSourceMetadata(const AudioPortConfig& portConfig) {
     PlaybackTrackMetadata trackMeta;
     trackMeta.usage = AudioUsage::MEDIA;
     trackMeta.contentType = AudioContentType::MUSIC;
@@ -388,7 +427,15 @@
     trackMeta.channelMask = portConfig.channelMask.value();
     SourceMetadata metadata;
     metadata.tracks.push_back(trackMeta);
-    return module->openOutputStream(portConfig.id, metadata, {}, &mStream);
+    return metadata;
+}
+
+template <>
+ScopedAStatus WithStream<IStreamOut>::SetUpNoChecks(IModule* module,
+                                                    const AudioPortConfig& portConfig) {
+    return module->openOutputStream(portConfig.id, GenerateSourceMetadata(portConfig),
+                                    ModuleConfig::generateOffloadInfoIfNeeded(portConfig),
+                                    &mStream);
 }
 
 class WithAudioPatch {
@@ -396,18 +443,19 @@
     WithAudioPatch() {}
     WithAudioPatch(const AudioPortConfig& srcPortConfig, const AudioPortConfig& sinkPortConfig)
         : mSrcPortConfig(srcPortConfig), mSinkPortConfig(sinkPortConfig) {}
+    WithAudioPatch(const WithAudioPatch&) = delete;
+    WithAudioPatch& operator=(const WithAudioPatch&) = delete;
     ~WithAudioPatch() {
         if (mModule != nullptr && mPatch.id != 0) {
-            Status status = mModule->resetAudioPatch(mPatch.id);
-            EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
-                    << status << "; patch id " << getId();
+            ScopedAStatus status = mModule->resetAudioPatch(mPatch.id);
+            EXPECT_EQ(EX_NONE, status.getExceptionCode()) << status << "; patch id " << getId();
         }
     }
     void SetUpPortConfigs(IModule* module) {
         ASSERT_NO_FATAL_FAILURE(mSrcPortConfig.SetUp(module));
         ASSERT_NO_FATAL_FAILURE(mSinkPortConfig.SetUp(module));
     }
-    Status SetUpNoChecks(IModule* module) {
+    ScopedAStatus SetUpNoChecks(IModule* module) {
         mModule = module;
         mPatch.sourcePortConfigIds = std::vector<int32_t>{mSrcPortConfig.getId()};
         mPatch.sinkPortConfigIds = std::vector<int32_t>{mSinkPortConfig.getId()};
@@ -415,8 +463,8 @@
     }
     void SetUp(IModule* module) {
         ASSERT_NO_FATAL_FAILURE(SetUpPortConfigs(module));
-        Status status = SetUpNoChecks(module);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode())
+        ScopedAStatus status = SetUpNoChecks(module);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode())
                 << status << "; source port config id " << mSrcPortConfig.getId()
                 << "; sink port config id " << mSinkPortConfig.getId();
     }
@@ -446,13 +494,13 @@
 TEST_P(AudioCoreModule, GetAudioPortsIsStable) {
     std::vector<AudioPort> ports1;
     {
-        Status status = module->getAudioPorts(&ports1);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioPorts(&ports1);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     std::vector<AudioPort> ports2;
     {
-        Status status = module->getAudioPorts(&ports2);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioPorts(&ports2);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     ASSERT_EQ(ports1.size(), ports2.size())
             << "Sizes of audio port arrays do not match across consequent calls to getAudioPorts";
@@ -464,13 +512,13 @@
 TEST_P(AudioCoreModule, GetAudioRoutesIsStable) {
     std::vector<AudioRoute> routes1;
     {
-        Status status = module->getAudioRoutes(&routes1);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioRoutes(&routes1);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     std::vector<AudioRoute> routes2;
     {
-        Status status = module->getAudioRoutes(&routes2);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioRoutes(&routes2);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     ASSERT_EQ(routes1.size(), routes2.size())
             << "Sizes of audio route arrays do not match across consequent calls to getAudioRoutes";
@@ -482,8 +530,8 @@
 TEST_P(AudioCoreModule, GetAudioRoutesAreValid) {
     std::vector<AudioRoute> routes;
     {
-        Status status = module->getAudioRoutes(&routes);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioRoutes(&routes);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     for (const auto& route : routes) {
         std::set<int32_t> sources(route.sourcePortIds.begin(), route.sourcePortIds.end());
@@ -500,8 +548,8 @@
     ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
     std::vector<AudioRoute> routes;
     {
-        Status status = module->getAudioRoutes(&routes);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioRoutes(&routes);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     for (const auto& route : routes) {
         EXPECT_EQ(1, portIds.count(route.sinkPortId))
@@ -520,8 +568,8 @@
     }
     for (const auto portId : portIds) {
         std::vector<AudioRoute> routes;
-        Status status = module->getAudioRoutesForAudioPort(portId, &routes);
-        EXPECT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioRoutesForAudioPort(portId, &routes);
+        EXPECT_EQ(EX_NONE, status.getExceptionCode()) << status;
         for (const auto& r : routes) {
             if (r.sinkPortId != portId) {
                 const auto& srcs = r.sourcePortIds;
@@ -532,8 +580,8 @@
     }
     for (const auto portId : GetNonExistentIds(portIds)) {
         std::vector<AudioRoute> routes;
-        Status status = module->getAudioRoutesForAudioPort(portId, &routes);
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        ScopedAStatus status = module->getAudioRoutesForAudioPort(portId, &routes);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                 << status << " returned for port ID " << portId;
     }
 }
@@ -541,8 +589,8 @@
 TEST_P(AudioCoreModule, CheckDevicePorts) {
     std::vector<AudioPort> ports;
     {
-        Status status = module->getAudioPorts(&ports);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioPorts(&ports);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     std::optional<int32_t> defaultOutput, defaultInput;
     std::set<AudioDevice> inputs, outputs;
@@ -590,8 +638,8 @@
 TEST_P(AudioCoreModule, CheckMixPorts) {
     std::vector<AudioPort> ports;
     {
-        Status status = module->getAudioPorts(&ports);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioPorts(&ports);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     std::optional<int32_t> primaryMixPort;
     constexpr int primaryOutputFlag = 1 << static_cast<int>(AudioOutputFlags::PRIMARY);
@@ -619,18 +667,24 @@
     }
     for (const auto portId : portIds) {
         AudioPort port;
-        Status status = module->getAudioPort(portId, &port);
-        EXPECT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioPort(portId, &port);
+        EXPECT_EQ(EX_NONE, status.getExceptionCode()) << status;
         EXPECT_EQ(portId, port.id);
     }
     for (const auto portId : GetNonExistentIds(portIds)) {
         AudioPort port;
-        Status status = module->getAudioPort(portId, &port);
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        ScopedAStatus status = module->getAudioPort(portId, &port);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                 << status << " returned for port ID " << portId;
     }
 }
 
+TEST_P(AudioCoreModule, SetUpModuleConfig) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    // Send the module config to logcat to facilitate failures investigation.
+    LOG(INFO) << "SetUpModuleConfig: " << moduleConfig->toString();
+}
+
 // Verify that HAL module reports for a connected device port at least one non-dynamic profile,
 // that is, a profile with actual supported configuration.
 // Note: This test relies on simulation of external device connections by the HAL module.
@@ -653,8 +707,8 @@
                   portConnected.get().ext.get<AudioPortExt::Tag::device>().device);
         // Verify that 'getAudioPort' and 'getAudioPorts' return the same connected port.
         AudioPort connectedPort;
-        Status status = module->getAudioPort(connectedPortId, &connectedPort);
-        EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
+        ScopedAStatus status = module->getAudioPort(connectedPortId, &connectedPort);
+        EXPECT_EQ(EX_NONE, status.getExceptionCode())
                 << status << " returned for getAudioPort port ID " << connectedPortId;
         EXPECT_EQ(portConnected.get(), connectedPort);
         const auto& portProfiles = connectedPort.profiles;
@@ -669,8 +723,8 @@
 
         std::vector<AudioPort> allPorts;
         {
-            Status status = module->getAudioPorts(&allPorts);
-            ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+            ScopedAStatus status = module->getAudioPorts(&allPorts);
+            ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
         }
         const auto allPortsIt = findById(allPorts, connectedPortId);
         EXPECT_NE(allPorts.end(), allPortsIt);
@@ -685,16 +739,16 @@
     ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
     for (const auto portConfigId : GetNonExistentIds(portConfigIds)) {
         {
-            sp<IStreamIn> stream;
-            Status status = module->openInputStream(portConfigId, {}, &stream);
-            EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+            std::shared_ptr<IStreamIn> stream;
+            ScopedAStatus status = module->openInputStream(portConfigId, {}, &stream);
+            EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                     << status << " openInputStream returned for port config ID " << portConfigId;
             EXPECT_EQ(nullptr, stream);
         }
         {
-            sp<IStreamOut> stream;
-            Status status = module->openOutputStream(portConfigId, {}, {}, &stream);
-            EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+            std::shared_ptr<IStreamOut> stream;
+            ScopedAStatus status = module->openOutputStream(portConfigId, {}, {}, &stream);
+            EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                     << status << " openOutputStream returned for port config ID " << portConfigId;
             EXPECT_EQ(nullptr, stream);
         }
@@ -711,8 +765,8 @@
     ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
     std::vector<AudioPortConfig> portConfigs;
     {
-        Status status = module->getAudioPortConfigs(&portConfigs);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioPortConfigs(&portConfigs);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     for (const auto& config : portConfigs) {
         EXPECT_EQ(1, portIds.count(config.portId))
@@ -724,8 +778,8 @@
     std::set<int32_t> portConfigIds;
     ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
     for (const auto portConfigId : GetNonExistentIds(portConfigIds)) {
-        Status status = module->resetAudioPortConfig(portConfigId);
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        ScopedAStatus status = module->resetAudioPortConfig(portConfigId);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                 << status << " returned for port config ID " << portConfigId;
     }
 }
@@ -735,19 +789,19 @@
 TEST_P(AudioCoreModule, ResetAudioPortConfigToInitialValue) {
     std::vector<AudioPortConfig> portConfigsBefore;
     {
-        Status status = module->getAudioPortConfigs(&portConfigsBefore);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioPortConfigs(&portConfigsBefore);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     // TODO: Change port configs according to port profiles.
     for (const auto& c : portConfigsBefore) {
-        Status status = module->resetAudioPortConfig(c.id);
-        EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
+        ScopedAStatus status = module->resetAudioPortConfig(c.id);
+        EXPECT_EQ(EX_NONE, status.getExceptionCode())
                 << status << " returned for port config ID " << c.id;
     }
     std::vector<AudioPortConfig> portConfigsAfter;
     {
-        Status status = module->getAudioPortConfigs(&portConfigsAfter);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioPortConfigs(&portConfigsAfter);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     for (const auto& c : portConfigsBefore) {
         auto afterIt = findById<AudioPortConfig>(portConfigsAfter, c.id);
@@ -770,8 +824,8 @@
     portConfig.portId = srcMixPort.value().id;
     {
         bool applied = true;
-        Status status = module->setAudioPortConfig(portConfig, &suggestedConfig, &applied);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode())
+        ScopedAStatus status = module->setAudioPortConfig(portConfig, &suggestedConfig, &applied);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode())
                 << status << "; Config: " << portConfig.toString();
         EXPECT_FALSE(applied);
     }
@@ -826,8 +880,8 @@
         AudioPortConfig portConfig, suggestedConfig;
         bool applied;
         portConfig.portId = portId;
-        Status status = module->setAudioPortConfig(portConfig, &suggestedConfig, &applied);
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        ScopedAStatus status = module->setAudioPortConfig(portConfig, &suggestedConfig, &applied);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                 << status << " returned for port ID " << portId;
         EXPECT_FALSE(suggestedConfig.format.has_value());
         EXPECT_FALSE(suggestedConfig.channelMask.has_value());
@@ -842,8 +896,8 @@
         AudioPortConfig portConfig, suggestedConfig;
         bool applied;
         portConfig.id = portConfigId;
-        Status status = module->setAudioPortConfig(portConfig, &suggestedConfig, &applied);
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        ScopedAStatus status = module->setAudioPortConfig(portConfig, &suggestedConfig, &applied);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                 << status << " returned for port config ID " << portConfigId;
         EXPECT_FALSE(suggestedConfig.format.has_value());
         EXPECT_FALSE(suggestedConfig.channelMask.has_value());
@@ -858,15 +912,15 @@
         GTEST_SKIP() << "No external devices in the module.";
     }
     AudioPort ignored;
-    WithDebugFlags doNotSimulateConnections(debug);
+    WithDebugFlags doNotSimulateConnections = WithDebugFlags::createNested(debug);
     doNotSimulateConnections.flags().simulateDeviceConnections = false;
     ASSERT_NO_FATAL_FAILURE(doNotSimulateConnections.SetUp(module.get()));
     for (const auto& port : ports) {
         AudioPort portWithData = port;
         portWithData.ext.get<AudioPortExt::Tag::device>().device.address =
                 GenerateUniqueDeviceAddress();
-        Status status = module->connectExternalDevice(portWithData, &ignored);
-        EXPECT_EQ(Status::EX_ILLEGAL_STATE, status.exceptionCode())
+        ScopedAStatus status = module->connectExternalDevice(portWithData, &ignored);
+        EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
                 << status << " returned for static port " << portWithData.toString();
     }
 }
@@ -881,8 +935,8 @@
     ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
     ModuleDebug midwayDebugChange = debug.flags();
     midwayDebugChange.simulateDeviceConnections = false;
-    Status status = module->setModuleDebug(midwayDebugChange);
-    EXPECT_EQ(Status::EX_ILLEGAL_STATE, status.exceptionCode())
+    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";
 }
@@ -894,39 +948,39 @@
     for (const auto portId : GetNonExistentIds(portIds)) {
         AudioPort invalidPort;
         invalidPort.id = portId;
-        Status status = module->connectExternalDevice(invalidPort, &ignored);
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        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(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                 << status << " returned for port ID " << portId
                 << " when setting DISCONNECTED state";
     }
 
     std::vector<AudioPort> ports;
     {
-        Status status = module->getAudioPorts(&ports);
-        ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+        ScopedAStatus status = module->getAudioPorts(&ports);
+        ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     for (const auto& port : ports) {
         if (port.ext.getTag() != AudioPortExt::Tag::device) {
-            Status status = module->connectExternalDevice(port, &ignored);
-            EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+            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(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+            EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                     << status << " returned for 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()) {
-                Status status = module->connectExternalDevice(port, &ignored);
-                EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+                ScopedAStatus status = module->connectExternalDevice(port, &ignored);
+                EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                         << status << " returned for permanently attached device port ID " << port.id
                         << " when setting CONNECTED state";
                 status = module->disconnectExternalDevice(port.id);
-                EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+                EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                         << status << " returned for permanently attached device port ID " << port.id
                         << " when setting DISCONNECTED state";
             }
@@ -943,8 +997,8 @@
         GTEST_SKIP() << "No external devices in the module.";
     }
     for (const auto& port : ports) {
-        Status status = module->disconnectExternalDevice(port.id);
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        ScopedAStatus status = module->disconnectExternalDevice(port.id);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                 << status << " returned when disconnecting already disconnected device port ID "
                 << port.id;
         AudioPort portWithData = port;
@@ -953,14 +1007,14 @@
         WithDevicePortConnectedState portConnected(portWithData);
         ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
         status = module->connectExternalDevice(portConnected.get(), &ignored);
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                 << status << " returned when trying to connect a connected device port "
                 << portConnected.get().toString();
         status = module->connectExternalDevice(portWithData, &ignored);
-        EXPECT_EQ(Status::EX_ILLEGAL_STATE, status.exceptionCode())
+        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.exceptionCode() == Status::EX_NONE) {
+        if (status.getExceptionCode() == EX_NONE) {
             ADD_FAILURE() << "Returned connected port " << ignored.toString() << " for template "
                           << portWithData.toString();
         }
@@ -984,8 +1038,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()));
-            Status status = module->disconnectExternalDevice(portConnected.getId());
-            EXPECT_EQ(Status::EX_ILLEGAL_STATE, status.exceptionCode())
+            ScopedAStatus status = module->disconnectExternalDevice(portConnected.getId());
+            EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
                     << status << " returned when trying to disconnect device port ID " << port.id
                     << " with active configuration " << config.getId();
         }
@@ -1001,8 +1055,8 @@
     for (const auto& port : ports) {
         std::vector<AudioRoute> routesBefore;
         {
-            Status status = module->getAudioRoutes(&routesBefore);
-            ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+            ScopedAStatus status = module->getAudioRoutes(&routesBefore);
+            ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
         }
 
         int32_t connectedPortId;
@@ -1012,32 +1066,32 @@
             connectedPortId = portConnected.getId();
             std::vector<AudioRoute> connectedPortRoutes;
             {
-                Status status =
+                ScopedAStatus status =
                         module->getAudioRoutesForAudioPort(connectedPortId, &connectedPortRoutes);
-                ASSERT_EQ(Status::EX_NONE, status.exceptionCode())
+                ASSERT_EQ(EX_NONE, status.getExceptionCode())
                         << status << " returned 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;
-                Status status = module->getAudioRoutes(&allRoutes);
-                ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+                ScopedAStatus status = module->getAudioRoutes(&allRoutes);
+                ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
                 ADD_FAILURE() << " no routes returned for the connected port "
                               << portConnected.get().toString()
                               << "; all routes: " << android::internal::ToString(allRoutes);
             }
         }
         std::vector<AudioRoute> ignored;
-        Status status = module->getAudioRoutesForAudioPort(connectedPortId, &ignored);
-        ASSERT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        ScopedAStatus status = module->getAudioRoutesForAudioPort(connectedPortId, &ignored);
+        ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                 << status << " returned when retrieving routes for released connected port id "
                 << connectedPortId;
 
         std::vector<AudioRoute> routesAfter;
         {
-            Status status = module->getAudioRoutes(&routesAfter);
-            ASSERT_EQ(Status::EX_NONE, status.exceptionCode()) << status;
+            ScopedAStatus status = module->getAudioRoutes(&routesAfter);
+            ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
         }
         ASSERT_EQ(routesBefore.size(), routesAfter.size())
                 << "Sizes of audio route arrays do not match after creating and "
@@ -1063,14 +1117,14 @@
         if (!portConfig.has_value()) {
             GTEST_SKIP() << "No mix port for attached devices";
         }
-        sp<Stream> heldStream;
+        std::shared_ptr<Stream> heldStream;
         {
             WithStream<Stream> stream(portConfig.value());
             ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get()));
-            heldStream = stream.get();
+            heldStream = stream.getSharedPointer();
         }
-        Status status = heldStream->close();
-        EXPECT_EQ(Status::EX_ILLEGAL_STATE, status.exceptionCode())
+        ScopedAStatus status = heldStream->close();
+        EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
                 << status << " when closing the stream twice";
     }
 
@@ -1107,12 +1161,11 @@
                     ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get()));
                 } else {
                     ASSERT_NO_FATAL_FAILURE(stream.SetUpPortConfig(module.get()));
-                    Status status = stream.SetUpNoChecks(module.get());
-                    EXPECT_EQ(Status::EX_ILLEGAL_STATE, status.exceptionCode())
+                    ScopedAStatus status = stream.SetUpNoChecks(module.get());
+                    EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
                             << status << " open" << direction(true)
-                            << "Stream"
-                               " returned for port config ID "
-                            << stream.getPortId() << ", maxOpenStreamCount is " << maxStreamCount;
+                            << "Stream returned for port config ID " << stream.getPortId()
+                            << ", maxOpenStreamCount is " << maxStreamCount;
                 }
             }
         }
@@ -1130,8 +1183,8 @@
         }
         WithStream<Stream> stream(portConfig.value());
         ASSERT_NO_FATAL_FAILURE(stream.SetUpPortConfig(module.get()));
-        Status status = stream.SetUpNoChecks(module.get());
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        ScopedAStatus status = stream.SetUpNoChecks(module.get());
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                 << status << " open" << direction(true) << "Stream returned for port config ID "
                 << stream.getPortId();
         EXPECT_EQ(nullptr, stream.get());
@@ -1152,8 +1205,8 @@
         }
         WithStream<Stream> stream(portConfig.value());
         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get()));
-        Status status = module->resetAudioPortConfig(stream.getPortId());
-        EXPECT_EQ(Status::EX_ILLEGAL_STATE, status.exceptionCode())
+        ScopedAStatus status = module->resetAudioPortConfig(stream.getPortId());
+        EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
                 << status << " returned for port config ID " << stream.getPortId();
     }
 
@@ -1161,8 +1214,8 @@
         WithStream<Stream> stream1(portConfig);
         ASSERT_NO_FATAL_FAILURE(stream1.SetUp(module.get()));
         WithStream<Stream> stream2;
-        Status status = stream2.SetUpNoChecks(module.get(), stream1.getPortConfig());
-        EXPECT_EQ(Status::EX_ILLEGAL_STATE, status.exceptionCode())
+        ScopedAStatus status = stream2.SetUpNoChecks(module.get(), stream1.getPortConfig());
+        EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
                 << status << " when opening " << direction(false)
                 << " stream twice for the same port config ID " << stream1.getPortId();
     }
@@ -1195,7 +1248,7 @@
     auto primaryPortIt = std::find_if(mixPorts.begin(), mixPorts.end(), [](const AudioPort& port) {
         constexpr int primaryOutputFlag = 1 << static_cast<int>(AudioOutputFlags::PRIMARY);
         return port.flags.getTag() == AudioIoFlags::Tag::output &&
-               ((port.flags.get<AudioIoFlags::Tag::output>() & primaryOutputFlag) != 0);
+               (port.flags.get<AudioIoFlags::Tag::output>() & primaryOutputFlag) != 0;
     });
     if (primaryPortIt == mixPorts.end()) {
         GTEST_SKIP() << "No primary mix port";
@@ -1208,6 +1261,31 @@
     EXPECT_NO_FATAL_FAILURE(OpenTwiceSamePortConfigImpl(portConfig.value()));
 }
 
+TEST_P(AudioStreamOut, RequireOffloadInfo) {
+    const auto mixPorts = moduleConfig->getMixPorts(false);
+    auto offloadPortIt = std::find_if(mixPorts.begin(), mixPorts.end(), [&](const AudioPort& port) {
+        constexpr int compressOffloadFlag = 1
+                                            << static_cast<int>(AudioOutputFlags::COMPRESS_OFFLOAD);
+        return port.flags.getTag() == AudioIoFlags::Tag::output &&
+               (port.flags.get<AudioIoFlags::Tag::output>() & compressOffloadFlag) != 0 &&
+               !moduleConfig->getAttachedSinkDevicesPortsForMixPort(port).empty();
+    });
+    if (offloadPortIt == mixPorts.end()) {
+        GTEST_SKIP()
+                << "No mix port for compressed offload that could be routed to attached devices";
+    }
+    const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, *offloadPortIt);
+    ASSERT_TRUE(portConfig.has_value())
+            << "No profiles specified for the compressed offload mix port";
+    std::shared_ptr<IStreamOut> ignored;
+    ScopedAStatus status = module->openOutputStream(portConfig.value().id,
+                                                    GenerateSourceMetadata(portConfig.value()),
+                                                    {} /* offloadInfo */, &ignored);
+    EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
+            << status
+            << " returned when no offload info is provided for a compressed offload mix port";
+}
+
 // Tests specific to audio patches. The fixure class is named 'AudioModulePatch'
 // to avoid clashing with 'AudioPatch' class.
 class AudioModulePatch : public AudioCoreModule {
@@ -1226,8 +1304,8 @@
         AudioPatch patch;
         patch.sourcePortConfigIds = sources;
         patch.sinkPortConfigIds = sinks;
-        Status status = module->setAudioPatch(patch, &patch);
-        ASSERT_EQ(expectedException, status.exceptionCode())
+        ScopedAStatus status = module->setAudioPatch(patch, &patch);
+        ASSERT_EQ(expectedException, status.getExceptionCode())
                 << status << ": patch source ids: " << android::internal::ToString(sources)
                 << "; sink ids: " << android::internal::ToString(sinks);
     }
@@ -1246,8 +1324,8 @@
                                           patch.get().sinkPortConfigIds.begin(),
                                           patch.get().sinkPortConfigIds.end());
         for (const auto portConfigId : sourceAndSinkPortConfigIds) {
-            Status status = module->resetAudioPortConfig(portConfigId);
-            EXPECT_EQ(Status::EX_ILLEGAL_STATE, status.exceptionCode())
+            ScopedAStatus status = module->resetAudioPortConfig(portConfigId);
+            EXPECT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode())
                     << status << " returned for port config ID " << portConfigId;
         }
     }
@@ -1266,22 +1344,22 @@
             ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
         }
         EXPECT_NO_FATAL_FAILURE(
-                SetInvalidPatchHelper(Status::EX_ILLEGAL_ARGUMENT, {}, {sinkPortConfig.getId()}));
+                SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT, {}, {sinkPortConfig.getId()}));
         EXPECT_NO_FATAL_FAILURE(SetInvalidPatchHelper(
-                Status::EX_ILLEGAL_ARGUMENT, {srcPortConfig.getId(), srcPortConfig.getId()},
+                EX_ILLEGAL_ARGUMENT, {srcPortConfig.getId(), srcPortConfig.getId()},
                 {sinkPortConfig.getId()}));
         EXPECT_NO_FATAL_FAILURE(
-                SetInvalidPatchHelper(Status::EX_ILLEGAL_ARGUMENT, {srcPortConfig.getId()}, {}));
+                SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT, {srcPortConfig.getId()}, {}));
         EXPECT_NO_FATAL_FAILURE(
-                SetInvalidPatchHelper(Status::EX_ILLEGAL_ARGUMENT, {srcPortConfig.getId()},
+                SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT, {srcPortConfig.getId()},
                                       {sinkPortConfig.getId(), sinkPortConfig.getId()}));
 
         std::set<int32_t> portConfigIds;
         ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
         for (const auto portConfigId : GetNonExistentIds(portConfigIds)) {
-            EXPECT_NO_FATAL_FAILURE(SetInvalidPatchHelper(
-                    Status::EX_ILLEGAL_ARGUMENT, {portConfigId}, {sinkPortConfig.getId()}));
-            EXPECT_NO_FATAL_FAILURE(SetInvalidPatchHelper(Status::EX_ILLEGAL_ARGUMENT,
+            EXPECT_NO_FATAL_FAILURE(SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT, {portConfigId},
+                                                          {sinkPortConfig.getId()}));
+            EXPECT_NO_FATAL_FAILURE(SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT,
                                                           {srcPortConfig.getId()}, {portConfigId}));
         }
     }
@@ -1293,8 +1371,8 @@
         }
         WithAudioPatch patch(srcSinkPair.value().first, srcSinkPair.value().second);
         ASSERT_NO_FATAL_FAILURE(patch.SetUpPortConfigs(module.get()));
-        Status status = patch.SetUpNoChecks(module.get());
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        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 "
                 << srcSinkPair.value().second.toString() << " that does not have a route";
@@ -1307,11 +1385,12 @@
         }
         for (const auto& srcSinkGroup : srcSinkGroups) {
             const auto& route = srcSinkGroup.first;
-            std::vector<WithAudioPatch> patches;
+            std::vector<std::unique_ptr<WithAudioPatch>> patches;
             for (const auto& srcSink : srcSinkGroup.second) {
                 if (!route.isExclusive) {
-                    patches.emplace_back(srcSink.first, srcSink.second);
-                    EXPECT_NO_FATAL_FAILURE(patches[patches.size() - 1].SetUp(module.get()));
+                    patches.push_back(
+                            std::make_unique<WithAudioPatch>(srcSink.first, srcSink.second));
+                    EXPECT_NO_FATAL_FAILURE(patches[patches.size() - 1]->SetUp(module.get()));
                 } else {
                     WithAudioPatch patch(srcSink.first, srcSink.second);
                     EXPECT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
@@ -1351,8 +1430,9 @@
         for (const auto patchId : GetNonExistentIds(patchIds)) {
             AudioPatch patchWithNonExistendId = patch.get();
             patchWithNonExistendId.id = patchId;
-            Status status = module->setAudioPatch(patchWithNonExistendId, &patchWithNonExistendId);
-            EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+            ScopedAStatus status =
+                    module->setAudioPatch(patchWithNonExistendId, &patchWithNonExistendId);
+            EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                     << status << " returned for patch ID " << patchId;
         }
     }
@@ -1375,8 +1455,8 @@
     std::set<int32_t> patchIds;
     ASSERT_NO_FATAL_FAILURE(GetAllPatchIds(&patchIds));
     for (const auto patchId : GetNonExistentIds(patchIds)) {
-        Status status = module->resetAudioPatch(patchId);
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, status.exceptionCode())
+        ScopedAStatus status = module->resetAudioPatch(patchId);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode())
                 << status << " returned for patch ID " << patchId;
     }
 }
@@ -1398,9 +1478,26 @@
                          android::PrintInstanceNameToString);
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioModulePatch);
 
+class TestExecutionTracer : public ::testing::EmptyTestEventListener {
+  public:
+    void OnTestStart(const ::testing::TestInfo& test_info) override {
+        TraceTestState("Started", test_info);
+    }
+
+    void OnTestEnd(const ::testing::TestInfo& test_info) override {
+        TraceTestState("Completed", test_info);
+    }
+
+  private:
+    static void TraceTestState(const std::string& state, const ::testing::TestInfo& test_info) {
+        LOG(INFO) << state << " " << test_info.test_suite_name() << "::" << test_info.name();
+    }
+};
+
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
-    ProcessState::self()->setThreadPoolMaxThreadCount(1);
-    ProcessState::self()->startThreadPool();
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
 }