Merge "ExternalCameraHAL: Check for empty native handle instead of null." into main
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index bb8d76f..9aa86b5 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -12,6 +12,7 @@
     vendor: true,
     shared_libs: [
         "libalsautilsv2",
+        "libaudio_aidl_conversion_common_ndk",
         "libaudioaidlcommon",
         "libaudioutils",
         "libbase",
@@ -19,6 +20,8 @@
         "libcutils",
         "libfmq",
         "libnbaio_mono",
+        "liblog",
+        "libmedia_helper",
         "libstagefright_foundation",
         "libtinyalsav2",
         "libutils",
@@ -31,6 +34,9 @@
         "libaudioaidl_headers",
         "libxsdc-utils",
     ],
+    cflags: [
+        "-DBACKEND_NDK",
+    ],
 }
 
 cc_library {
@@ -78,6 +84,7 @@
         "Stream.cpp",
         "StreamSwitcher.cpp",
         "Telephony.cpp",
+        "XsdcConversion.cpp",
         "alsa/Mixer.cpp",
         "alsa/ModuleAlsa.cpp",
         "alsa/StreamAlsa.cpp",
@@ -172,6 +179,7 @@
         "libbase",
         "libbinder_ndk",
         "libcutils",
+        "libfmq",
         "libmedia_helper",
         "libstagefright_foundation",
         "libutils",
@@ -184,9 +192,11 @@
     ],
     generated_sources: [
         "audio_policy_configuration_aidl_default",
+        "audio_policy_engine_configuration_aidl_default",
     ],
     generated_headers: [
         "audio_policy_configuration_aidl_default",
+        "audio_policy_engine_configuration_aidl_default",
     ],
     srcs: [
         "AudioPolicyConfigXmlConverter.cpp",
diff --git a/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp b/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp
index 7452c8e..2f1282a 100644
--- a/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp
+++ b/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp
@@ -30,6 +30,7 @@
 
 #include "core-impl/AidlConversionXsdc.h"
 #include "core-impl/AudioPolicyConfigXmlConverter.h"
+#include "core-impl/XsdcConversion.h"
 
 using aidl::android::media::audio::common::AudioFormatDescription;
 using aidl::android::media::audio::common::AudioHalEngineConfig;
@@ -37,60 +38,39 @@
 using aidl::android::media::audio::common::AudioHalVolumeGroup;
 using aidl::android::media::audio::common::AudioStreamType;
 
-namespace xsd = android::audio::policy::configuration;
+namespace ap_xsd = android::audio::policy::configuration;
 
 namespace aidl::android::hardware::audio::core::internal {
 
 static const int kDefaultVolumeIndexMin = 0;
 static const int kDefaultVolumeIndexMax = 100;
 static const int KVolumeIndexDeferredToAudioService = -1;
-/**
- * Valid curve points take the form "<index>,<attenuationMb>", where the index
- * must be in the range [0,100]. kInvalidCurvePointIndex is used to indicate
- * that a point was formatted incorrectly (e.g. if a vendor accidentally typed a
- * '.' instead of a ',' in their XML) -- using such a curve point will result in
- * failed VTS tests.
- */
-static const int8_t kInvalidCurvePointIndex = -1;
 
-AudioHalVolumeCurve::CurvePoint AudioPolicyConfigXmlConverter::convertCurvePointToAidl(
-        const std::string& xsdcCurvePoint) {
-    AudioHalVolumeCurve::CurvePoint aidlCurvePoint{};
-    if (sscanf(xsdcCurvePoint.c_str(), "%" SCNd8 ",%d", &aidlCurvePoint.index,
-               &aidlCurvePoint.attenuationMb) != 2) {
-        aidlCurvePoint.index = kInvalidCurvePointIndex;
-    }
-    return aidlCurvePoint;
-}
-
-AudioHalVolumeCurve AudioPolicyConfigXmlConverter::convertVolumeCurveToAidl(
-        const xsd::Volume& xsdcVolumeCurve) {
+ConversionResult<AudioHalVolumeCurve> AudioPolicyConfigXmlConverter::convertVolumeCurveToAidl(
+        const ap_xsd::Volume& xsdcVolumeCurve) {
     AudioHalVolumeCurve aidlVolumeCurve;
     aidlVolumeCurve.deviceCategory =
             static_cast<AudioHalVolumeCurve::DeviceCategory>(xsdcVolumeCurve.getDeviceCategory());
     if (xsdcVolumeCurve.hasRef()) {
         if (mVolumesReferenceMap.empty()) {
-            mVolumesReferenceMap = generateReferenceMap<xsd::Volumes, xsd::Reference>(
+            mVolumesReferenceMap = generateReferenceMap<ap_xsd::Volumes, ap_xsd::Reference>(
                     getXsdcConfig()->getVolumes());
         }
-        aidlVolumeCurve.curvePoints =
-                convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
+        aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
+                (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
                         mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
-                        std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this,
-                                  std::placeholders::_1));
+                        &convertCurvePointToAidl)));
     } else {
-        aidlVolumeCurve.curvePoints =
-                convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
-                        xsdcVolumeCurve.getPoint(),
-                        std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this,
-                                  std::placeholders::_1));
+        aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
+                (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+                        xsdcVolumeCurve.getPoint(), &convertCurvePointToAidl)));
     }
     return aidlVolumeCurve;
 }
 
-void AudioPolicyConfigXmlConverter::mapStreamToVolumeCurve(const xsd::Volume& xsdcVolumeCurve) {
+void AudioPolicyConfigXmlConverter::mapStreamToVolumeCurve(const ap_xsd::Volume& xsdcVolumeCurve) {
     mStreamToVolumeCurvesMap[xsdcVolumeCurve.getStream()].push_back(
-            convertVolumeCurveToAidl(xsdcVolumeCurve));
+            VALUE_OR_FATAL(convertVolumeCurveToAidl(xsdcVolumeCurve)));
 }
 
 const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getSurroundSoundConfig() {
@@ -109,6 +89,11 @@
     return aidlSurroundSoundConfig;
 }
 
+std::unique_ptr<AudioPolicyConfigXmlConverter::ModuleConfigs>
+AudioPolicyConfigXmlConverter::releaseModuleConfigs() {
+    return std::move(mModuleConfigurations);
+}
+
 const AudioHalEngineConfig& AudioPolicyConfigXmlConverter::getAidlEngineConfig() {
     if (mAidlEngineConfig.volumeGroups.empty() && getXsdcConfig() &&
         getXsdcConfig()->hasVolumes()) {
@@ -160,8 +145,8 @@
 
 void AudioPolicyConfigXmlConverter::mapStreamsToVolumeCurves() {
     if (getXsdcConfig()->hasVolumes()) {
-        for (const xsd::Volumes& xsdcWrapperType : getXsdcConfig()->getVolumes()) {
-            for (const xsd::Volume& xsdcVolume : xsdcWrapperType.getVolume()) {
+        for (const ap_xsd::Volumes& xsdcWrapperType : getXsdcConfig()->getVolumes()) {
+            for (const ap_xsd::Volume& xsdcVolume : xsdcWrapperType.getVolume()) {
                 mapStreamToVolumeCurve(xsdcVolume);
             }
         }
@@ -171,7 +156,7 @@
 void AudioPolicyConfigXmlConverter::addVolumeGroupstoEngineConfig() {
     for (const auto& [xsdcStream, volumeCurves] : mStreamToVolumeCurvesMap) {
         AudioHalVolumeGroup volumeGroup;
-        volumeGroup.name = xsd::toString(xsdcStream);
+        volumeGroup.name = ap_xsd::toString(xsdcStream);
         if (static_cast<int>(xsdcStream) >= AUDIO_STREAM_PUBLIC_CNT) {
             volumeGroup.minIndex = kDefaultVolumeIndexMin;
             volumeGroup.maxIndex = kDefaultVolumeIndexMax;
@@ -190,4 +175,24 @@
         addVolumeGroupstoEngineConfig();
     }
 }
+
+void AudioPolicyConfigXmlConverter::init() {
+    if (!getXsdcConfig()->hasModules()) return;
+    for (const ap_xsd::Modules& xsdcModulesType : getXsdcConfig()->getModules()) {
+        if (!xsdcModulesType.has_module()) continue;
+        for (const ap_xsd::Modules::Module& xsdcModule : xsdcModulesType.get_module()) {
+            // 'primary' in the XML schema used by HIDL is equivalent to 'default' module.
+            const std::string name =
+                    xsdcModule.getName() != "primary" ? xsdcModule.getName() : "default";
+            if (name != "r_submix") {
+                mModuleConfigurations->emplace_back(
+                        name, VALUE_OR_FATAL(convertModuleConfigToAidl(xsdcModule)));
+            } else {
+                // See the note on the 'getRSubmixConfiguration' function.
+                mModuleConfigurations->emplace_back(name, nullptr);
+            }
+        }
+    }
+}
+
 }  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index 635a25b..d09552b 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -41,8 +41,8 @@
 using aidl::android::media::audio::common::AudioPortMixExt;
 using aidl::android::media::audio::common::AudioProfile;
 using aidl::android::media::audio::common::Int;
-using aidl::android::media::audio::common::MicrophoneInfo;
 using aidl::android::media::audio::common::PcmType;
+using Configuration = aidl::android::hardware::audio::core::Module::Configuration;
 
 namespace aidl::android::hardware::audio::core::internal {
 
@@ -105,15 +105,11 @@
     return port;
 }
 
-static AudioPortConfig createPortConfig(int32_t id, int32_t portId, PcmType pcmType, int32_t layout,
-                                        int32_t sampleRate, int32_t flags, bool isInput,
-                                        const AudioPortExt& ext) {
+static AudioPortConfig createDynamicPortConfig(int32_t id, int32_t portId, int32_t flags,
+                                               bool isInput, const AudioPortExt& ext) {
     AudioPortConfig config;
     config.id = id;
     config.portId = portId;
-    config.sampleRate = Int{.value = sampleRate};
-    config.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout);
-    config.format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType};
     config.gain = AudioGainConfig();
     config.flags = isInput ? AudioIoFlags::make<AudioIoFlags::Tag::input>(flags)
                            : AudioIoFlags::make<AudioIoFlags::Tag::output>(flags);
@@ -121,6 +117,16 @@
     return config;
 }
 
+static AudioPortConfig createPortConfig(int32_t id, int32_t portId, PcmType pcmType, int32_t layout,
+                                        int32_t sampleRate, int32_t flags, bool isInput,
+                                        const AudioPortExt& ext) {
+    AudioPortConfig config = createDynamicPortConfig(id, portId, flags, isInput, ext);
+    config.sampleRate = Int{.value = sampleRate};
+    config.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout);
+    config.format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType};
+    return config;
+}
+
 static AudioRoute createRoute(const std::vector<AudioPort>& sources, const AudioPort& sink) {
     AudioRoute route;
     route.sinkPortId = sink.id;
@@ -129,6 +135,22 @@
     return route;
 }
 
+std::vector<AudioProfile> getStandard16And24BitPcmAudioProfiles() {
+    auto createStdPcmAudioProfile = [](const PcmType& pcmType) {
+        return AudioProfile{
+                .format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType},
+                .channelMasks = {AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                                         AudioChannelLayout::LAYOUT_MONO),
+                                 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                                         AudioChannelLayout::LAYOUT_STEREO)},
+                .sampleRates = {8000, 11025, 16000, 32000, 44100, 48000}};
+    };
+    return {
+            createStdPcmAudioProfile(PcmType::INT_16_BIT),
+            createStdPcmAudioProfile(PcmType::INT_24_BIT),
+    };
+}
+
 // Primary (default) configuration:
 //
 // Device ports:
@@ -147,8 +169,7 @@
 //  * "primary output", PRIMARY, 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //  * "primary input", 1 max open, 1 max active stream
-//    - profile PCM 16-bit; MONO, STEREO;
-//        8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //  * "telephony_tx", 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //  * "telephony_rx", 1 max open, 1 max active stream
@@ -164,11 +185,11 @@
 //  "FM Tuner" -> "fm_tuner"
 //
 // Initial port configs:
-//  * "Speaker" device port: PCM 16-bit; STEREO; 48000
-//  * "Built-In Mic" device port: PCM 16-bit; MONO; 48000
-//  * "Telephony Tx" device port: PCM 16-bit; MONO; 48000
-//  * "Telephony Rx" device port: PCM 16-bit; MONO; 48000
-//  * "FM Tuner" device port: PCM 16-bit; STEREO; 48000
+//  * "Speaker" device port: dynamic configuration
+//  * "Built-In Mic" device port: dynamic configuration
+//  * "Telephony Tx" device port: dynamic configuration
+//  * "Telephony Rx" device port: dynamic configuration
+//  * "FM Tuner" device port: dynamic configuration
 //
 std::unique_ptr<Configuration> getPrimaryConfiguration() {
     static const Configuration configuration = []() {
@@ -186,9 +207,8 @@
                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
         c.ports.push_back(speakerOutDevice);
         c.initialConfigs.push_back(
-                createPortConfig(speakerOutDevice.id, speakerOutDevice.id, PcmType::INT_16_BIT,
-                                 AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
-                                 createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
+                createDynamicPortConfig(speakerOutDevice.id, speakerOutDevice.id, 0, false,
+                                        createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
 
         AudioPort micInDevice =
                 createPort(c.nextPortId++, "Built-In Mic", 0, true,
@@ -196,35 +216,31 @@
                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
         c.ports.push_back(micInDevice);
         c.initialConfigs.push_back(
-                createPortConfig(micInDevice.id, micInDevice.id, PcmType::INT_16_BIT,
-                                 AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
-                                 createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
+                createDynamicPortConfig(micInDevice.id, micInDevice.id, 0, true,
+                                        createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
 
         AudioPort telephonyTxOutDevice =
                 createPort(c.nextPortId++, "Telephony Tx", 0, false,
                            createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0));
         c.ports.push_back(telephonyTxOutDevice);
         c.initialConfigs.push_back(
-                createPortConfig(telephonyTxOutDevice.id, telephonyTxOutDevice.id,
-                                 PcmType::INT_16_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
-                                 false, createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0)));
+                createDynamicPortConfig(telephonyTxOutDevice.id, telephonyTxOutDevice.id, 0, false,
+                                        createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0)));
 
         AudioPort telephonyRxInDevice =
                 createPort(c.nextPortId++, "Telephony Rx", 0, true,
                            createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0));
         c.ports.push_back(telephonyRxInDevice);
         c.initialConfigs.push_back(
-                createPortConfig(telephonyRxInDevice.id, telephonyRxInDevice.id,
-                                 PcmType::INT_16_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
-                                 true, createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0)));
+                createDynamicPortConfig(telephonyRxInDevice.id, telephonyRxInDevice.id, 0, true,
+                                        createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0)));
 
         AudioPort fmTunerInDevice = createPort(c.nextPortId++, "FM Tuner", 0, true,
                                                createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0));
         c.ports.push_back(fmTunerInDevice);
         c.initialConfigs.push_back(
-                createPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, PcmType::INT_16_BIT,
-                                 AudioChannelLayout::LAYOUT_STEREO, 48000, 0, true,
-                                 createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0)));
+                createDynamicPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, 0, true,
+                                        createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0)));
 
         // Mix ports
 
@@ -273,13 +289,6 @@
 
         c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
 
-        MicrophoneInfo mic;
-        mic.id = "mic";
-        mic.device = micInDevice.ext.get<AudioPortExt::Tag::device>().device;
-        mic.group = 0;
-        mic.indexInTheGroup = 0;
-        c.microphones = std::vector<MicrophoneInfo>{mic};
-
         return c;
     }();
     return std::make_unique<Configuration>(configuration);
@@ -287,13 +296,15 @@
 
 // Note: When transitioning to loading of XML configs, either keep the configuration
 // of the remote submix sources from this static configuration, or update the XML
-// config to match it. There are two reasons for that:
-//   1. The canonical r_submix configuration only lists 'STEREO' and '48000',
+// config to match it. There are several reasons for that:
+//   1. The "Remote Submix In" device is listed in the XML config as "attached",
+//      however in the AIDL scheme its device type has a "virtual" connection.
+//   2. The canonical r_submix configuration only lists 'STEREO' and '48000',
 //      however the framework attempts to open streams for other sample rates
 //      as well. The legacy r_submix implementation allowed that, but libaudiohal@aidl
 //      will not find a mix port to use. Because of that, list all channel
 //      masks and sample rates that the legacy implementation allowed.
-//   2. The legacy implementation had a hard limit on the number of routes (10),
+//   3. The legacy implementation had a hard limit on the number of routes (10),
 //      and this is checked indirectly by AudioPlaybackCaptureTest#testPlaybackCaptureDoS
 //      CTS test. Instead of hardcoding the number of routes, we can use
 //      "maxOpen/ActiveStreamCount" to enforce a similar limit. However, the canonical
@@ -331,15 +342,15 @@
                 createPort(c.nextPortId++, "Remote Submix Out", 0, false,
                            createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0,
                                            AudioDeviceDescription::CONNECTION_VIRTUAL));
-        rsubmixOutDevice.profiles = standardPcmAudioProfiles;
         c.ports.push_back(rsubmixOutDevice);
+        c.connectedProfiles[rsubmixOutDevice.id] = standardPcmAudioProfiles;
 
         AudioPort rsubmixInDevice =
                 createPort(c.nextPortId++, "Remote Submix In", 0, true,
                            createDeviceExt(AudioDeviceType::IN_SUBMIX, 0,
                                            AudioDeviceDescription::CONNECTION_VIRTUAL));
-        rsubmixInDevice.profiles = standardPcmAudioProfiles;
         c.ports.push_back(rsubmixInDevice);
+        c.connectedProfiles[rsubmixInDevice.id] = standardPcmAudioProfiles;
 
         // Mix ports
 
@@ -384,7 +395,7 @@
 //  * "usb_device output" -> "USB Headset Out"
 //  * "USB Device In", "USB Headset In" -> "usb_device input"
 //
-// Profiles for device port connected state:
+// Profiles for device port connected state (when simulating connections):
 //  * "USB Device Out", "USB Headset Out":
 //    - profile PCM 16-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
 //    - profile PCM 24-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
@@ -461,9 +472,9 @@
 //  * "Test In", IN_AFE_PROXY
 //    - no profiles specified
 //  * "Wired Headset", OUT_HEADSET
-//    - profile PCM 24-bit; STEREO; 48000
+//    - no profiles specified
 //  * "Wired Headset Mic", IN_HEADSET
-//    - profile PCM 24-bit; MONO; 48000
+//    - no profiles specified
 //
 // Mix ports:
 //  * "test output", 1 max open, 1 max active stream
@@ -486,6 +497,10 @@
 //  * "Test Out" device port: PCM 24-bit; STEREO; 48000
 //  * "Test In" device port: PCM 24-bit; MONO; 48000
 //
+// Profiles for device port connected state (when simulating connections):
+//  * "Wired Headset": dynamic profiles
+//  * "Wired Headset Mic": dynamic profiles
+//
 std::unique_ptr<Configuration> getStubConfiguration() {
     static const Configuration configuration = []() {
         Configuration c;
@@ -504,8 +519,6 @@
                 createPort(c.nextPortId++, "Wired Headset", 0, false,
                            createDeviceExt(AudioDeviceType::OUT_HEADSET, 0,
                                            AudioDeviceDescription::CONNECTION_ANALOG));
-        headsetOutDevice.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
         c.ports.push_back(headsetOutDevice);
 
         AudioPort testInDevice = createPort(c.nextPortId++, "Test In", 0, true,
@@ -520,8 +533,6 @@
                 createPort(c.nextPortId++, "Wired Headset Mic", 0, true,
                            createDeviceExt(AudioDeviceType::IN_HEADSET, 0,
                                            AudioDeviceDescription::CONNECTION_ANALOG));
-        headsetInDevice.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_MONO}, {48000}));
         c.ports.push_back(headsetInDevice);
 
         // Mix ports
@@ -553,24 +564,24 @@
                               {44100, 48000}));
         c.ports.push_back(compressedOffloadOutMix);
 
-        AudioPort testInMIx =
+        AudioPort testInMix =
                 createPort(c.nextPortId++, "test input", 0, true, createPortMixExt(2, 2));
-        testInMIx.profiles.push_back(
+        testInMix.profiles.push_back(
                 createProfile(PcmType::INT_16_BIT,
                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
                                AudioChannelLayout::LAYOUT_FRONT_BACK},
                               {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
-        testInMIx.profiles.push_back(
+        testInMix.profiles.push_back(
                 createProfile(PcmType::INT_24_BIT,
                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
                                AudioChannelLayout::LAYOUT_FRONT_BACK},
                               {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
-        c.ports.push_back(testInMIx);
+        c.ports.push_back(testInMix);
 
         c.routes.push_back(
                 createRoute({testOutMix, testFastOutMix, compressedOffloadOutMix}, testOutDevice));
         c.routes.push_back(createRoute({testOutMix}, headsetOutDevice));
-        c.routes.push_back(createRoute({testInDevice, headsetInDevice}, testInMIx));
+        c.routes.push_back(createRoute({testInDevice, headsetInDevice}, testInMix));
 
         c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
 
@@ -603,11 +614,19 @@
 //  "a2dp output" -> "BT A2DP Speaker"
 //  "hearing aid output" -> "BT Hearing Aid Out"
 //
+// Profiles for device port connected state (when simulating connections):
+//  * "BT A2DP Out", "BT A2DP Headphones", "BT A2DP Speaker":
+//    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
+//  * "BT Hearing Aid Out":
+//    - profile PCM 16-bit; STEREO; 16000, 24000
+//
 std::unique_ptr<Configuration> getBluetoothConfiguration() {
     static const Configuration configuration = []() {
         const std::vector<AudioProfile> standardPcmAudioProfiles = {
                 createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO},
                               {44100, 48000, 88200, 96000})};
+        const std::vector<AudioProfile> hearingAidAudioProfiles = {createProfile(
+                PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000, 24000})};
         Configuration c;
 
         // Device ports
@@ -645,8 +664,7 @@
                            createDeviceExt(AudioDeviceType::OUT_HEARING_AID, 0,
                                            AudioDeviceDescription::CONNECTION_WIRELESS));
         c.ports.push_back(btOutHearingAid);
-        c.connectedProfiles[btOutHearingAid.id] = std::vector<AudioProfile>(
-                {createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000})});
+        c.connectedProfiles[btOutHearingAid.id] = hearingAidAudioProfiles;
 
         // Mix ports
         AudioPort btOutMix =
@@ -655,8 +673,7 @@
 
         AudioPort btHearingOutMix =
                 createPort(c.nextPortId++, "hearing aid output", 0, false, createPortMixExt(1, 1));
-        btHearingOutMix.profiles.push_back(createProfile(
-                PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000, 24000}));
+        btHearingOutMix.profiles = hearingAidAudioProfiles;
         c.ports.push_back(btHearingOutMix);
 
         c.routes.push_back(createRoute({btOutMix}, btOutDevice));
@@ -669,4 +686,19 @@
     return std::make_unique<Configuration>(configuration);
 }
 
+std::unique_ptr<Module::Configuration> getConfiguration(Module::Type moduleType) {
+    switch (moduleType) {
+        case Module::Type::DEFAULT:
+            return getPrimaryConfiguration();
+        case Module::Type::R_SUBMIX:
+            return getRSubmixConfiguration();
+        case Module::Type::STUB:
+            return getStubConfiguration();
+        case Module::Type::USB:
+            return getUsbConfiguration();
+        case Module::Type::BLUETOOTH:
+            return getBluetoothConfiguration();
+    }
+}
+
 }  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/EngineConfigXmlConverter.cpp b/audio/aidl/default/EngineConfigXmlConverter.cpp
index 96b555c..631cdce 100644
--- a/audio/aidl/default/EngineConfigXmlConverter.cpp
+++ b/audio/aidl/default/EngineConfigXmlConverter.cpp
@@ -20,11 +20,14 @@
 #include <functional>
 #include <unordered_map>
 
+#define LOG_TAG "AHAL_Config"
 #include <aidl/android/media/audio/common/AudioFlag.h>
 #include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
 #include <aidl/android/media/audio/common/AudioProductStrategyType.h>
+#include <android-base/logging.h>
 
 #include "core-impl/EngineConfigXmlConverter.h"
+#include "core-impl/XsdcConversion.h"
 
 using aidl::android::media::audio::common::AudioAttributes;
 using aidl::android::media::audio::common::AudioContentType;
@@ -40,20 +43,13 @@
 using aidl::android::media::audio::common::AudioSource;
 using aidl::android::media::audio::common::AudioStreamType;
 using aidl::android::media::audio::common::AudioUsage;
+using ::android::BAD_VALUE;
+using ::android::base::unexpected;
 
-namespace xsd = android::audio::policy::engine::configuration;
+namespace eng_xsd = android::audio::policy::engine::configuration;
 
 namespace aidl::android::hardware::audio::core::internal {
 
-/**
- * Valid curve points take the form "<index>,<attenuationMb>", where the index
- * must be in the range [0,100]. kInvalidCurvePointIndex is used to indicate
- * that a point was formatted incorrectly (e.g. if a vendor accidentally typed a
- * '.' instead of a ',' in their XML)-- using such a curve point will result in
- * failed VTS tests.
- */
-static const int8_t kInvalidCurvePointIndex = -1;
-
 void EngineConfigXmlConverter::initProductStrategyMap() {
 #define STRATEGY_ENTRY(name) {"STRATEGY_" #name, static_cast<int>(AudioProductStrategyType::name)}
 
@@ -68,7 +64,7 @@
 #undef STRATEGY_ENTRY
 }
 
-int EngineConfigXmlConverter::convertProductStrategyNameToAidl(
+ConversionResult<int> EngineConfigXmlConverter::convertProductStrategyNameToAidl(
         const std::string& xsdcProductStrategyName) {
     const auto [it, success] = mProductStrategyMap.insert(
             std::make_pair(xsdcProductStrategyName, mNextVendorStrategy));
@@ -85,12 +81,12 @@
             (attributes.tags.empty()));
 }
 
-AudioAttributes EngineConfigXmlConverter::convertAudioAttributesToAidl(
-        const xsd::AttributesType& xsdcAudioAttributes) {
+ConversionResult<AudioAttributes> EngineConfigXmlConverter::convertAudioAttributesToAidl(
+        const eng_xsd::AttributesType& xsdcAudioAttributes) {
     if (xsdcAudioAttributes.hasAttributesRef()) {
         if (mAttributesReferenceMap.empty()) {
             mAttributesReferenceMap =
-                    generateReferenceMap<xsd::AttributesRef, xsd::AttributesRefType>(
+                    generateReferenceMap<eng_xsd::AttributesRef, eng_xsd::AttributesRefType>(
                             getXsdcConfig()->getAttributesRef());
         }
         return convertAudioAttributesToAidl(
@@ -111,16 +107,16 @@
                 static_cast<AudioSource>(xsdcAudioAttributes.getFirstSource()->getValue());
     }
     if (xsdcAudioAttributes.hasFlags()) {
-        std::vector<xsd::FlagType> xsdcFlagTypeVec =
+        std::vector<eng_xsd::FlagType> xsdcFlagTypeVec =
                 xsdcAudioAttributes.getFirstFlags()->getValue();
-        for (const xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) {
-            if (xsdcFlagType != xsd::FlagType::AUDIO_FLAG_NONE) {
+        for (const eng_xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) {
+            if (xsdcFlagType != eng_xsd::FlagType::AUDIO_FLAG_NONE) {
                 aidlAudioAttributes.flags |= 1 << (static_cast<int>(xsdcFlagType) - 1);
             }
         }
     }
     if (xsdcAudioAttributes.hasBundle()) {
-        const xsd::BundleType* xsdcBundle = xsdcAudioAttributes.getFirstBundle();
+        const eng_xsd::BundleType* xsdcBundle = xsdcAudioAttributes.getFirstBundle();
         aidlAudioAttributes.tags[0] = xsdcBundle->getKey() + "=" + xsdcBundle->getValue();
     }
     if (isDefaultAudioAttributes(aidlAudioAttributes)) {
@@ -129,53 +125,54 @@
     return aidlAudioAttributes;
 }
 
-AudioHalAttributesGroup EngineConfigXmlConverter::convertAttributesGroupToAidl(
-        const xsd::AttributesGroup& xsdcAttributesGroup) {
+ConversionResult<AudioHalAttributesGroup> EngineConfigXmlConverter::convertAttributesGroupToAidl(
+        const eng_xsd::AttributesGroup& xsdcAttributesGroup) {
     AudioHalAttributesGroup aidlAttributesGroup;
     static const int kStreamTypeEnumOffset =
-            static_cast<int>(xsd::Stream::AUDIO_STREAM_VOICE_CALL) -
+            static_cast<int>(eng_xsd::Stream::AUDIO_STREAM_VOICE_CALL) -
             static_cast<int>(AudioStreamType::VOICE_CALL);
     aidlAttributesGroup.streamType = static_cast<AudioStreamType>(
             static_cast<int>(xsdcAttributesGroup.getStreamType()) - kStreamTypeEnumOffset);
     aidlAttributesGroup.volumeGroupName = xsdcAttributesGroup.getVolumeGroup();
     if (xsdcAttributesGroup.hasAttributes_optional()) {
         aidlAttributesGroup.attributes =
-                convertCollectionToAidlUnchecked<xsd::AttributesType, AudioAttributes>(
+                VALUE_OR_FATAL((convertCollectionToAidl<eng_xsd::AttributesType, AudioAttributes>(
                         xsdcAttributesGroup.getAttributes_optional(),
                         std::bind(&EngineConfigXmlConverter::convertAudioAttributesToAidl, this,
-                                  std::placeholders::_1));
+                                  std::placeholders::_1))));
     } else if (xsdcAttributesGroup.hasContentType_optional() ||
                xsdcAttributesGroup.hasUsage_optional() ||
                xsdcAttributesGroup.hasSource_optional() ||
                xsdcAttributesGroup.hasFlags_optional() ||
                xsdcAttributesGroup.hasBundle_optional()) {
-        aidlAttributesGroup.attributes.push_back(convertAudioAttributesToAidl(xsd::AttributesType(
-                xsdcAttributesGroup.getContentType_optional(),
-                xsdcAttributesGroup.getUsage_optional(), xsdcAttributesGroup.getSource_optional(),
-                xsdcAttributesGroup.getFlags_optional(), xsdcAttributesGroup.getBundle_optional(),
-                std::nullopt)));
+        aidlAttributesGroup.attributes.push_back(VALUE_OR_FATAL(convertAudioAttributesToAidl(
+                eng_xsd::AttributesType(xsdcAttributesGroup.getContentType_optional(),
+                                        xsdcAttributesGroup.getUsage_optional(),
+                                        xsdcAttributesGroup.getSource_optional(),
+                                        xsdcAttributesGroup.getFlags_optional(),
+                                        xsdcAttributesGroup.getBundle_optional(), std::nullopt))));
 
     } else {
-        // do nothing;
-        // TODO: check if this is valid or if we should treat as an error.
-        // Currently, attributes are not mandatory in schema, but an AttributesGroup
-        // without attributes does not make much sense.
+        LOG(ERROR) << __func__ << " Review Audio Policy config: no audio attributes provided for "
+                   << aidlAttributesGroup.toString();
+        return unexpected(BAD_VALUE);
     }
     return aidlAttributesGroup;
 }
 
-AudioHalProductStrategy EngineConfigXmlConverter::convertProductStrategyToAidl(
-        const xsd::ProductStrategies::ProductStrategy& xsdcProductStrategy) {
+ConversionResult<AudioHalProductStrategy> EngineConfigXmlConverter::convertProductStrategyToAidl(
+        const eng_xsd::ProductStrategies::ProductStrategy& xsdcProductStrategy) {
     AudioHalProductStrategy aidlProductStrategy;
 
-    aidlProductStrategy.id = convertProductStrategyNameToAidl(xsdcProductStrategy.getName());
+    aidlProductStrategy.id =
+            VALUE_OR_FATAL(convertProductStrategyNameToAidl(xsdcProductStrategy.getName()));
 
     if (xsdcProductStrategy.hasAttributesGroup()) {
-        aidlProductStrategy.attributesGroups =
-                convertCollectionToAidlUnchecked<xsd::AttributesGroup, AudioHalAttributesGroup>(
+        aidlProductStrategy.attributesGroups = VALUE_OR_FATAL(
+                (convertCollectionToAidl<eng_xsd::AttributesGroup, AudioHalAttributesGroup>(
                         xsdcProductStrategy.getAttributesGroup(),
                         std::bind(&EngineConfigXmlConverter::convertAttributesGroupToAidl, this,
-                                  std::placeholders::_1));
+                                  std::placeholders::_1))));
     }
     if ((mDefaultProductStrategyId != std::nullopt) && (mDefaultProductStrategyId.value() == -1)) {
         mDefaultProductStrategyId = aidlProductStrategy.id;
@@ -183,82 +180,42 @@
     return aidlProductStrategy;
 }
 
-AudioHalVolumeCurve::CurvePoint EngineConfigXmlConverter::convertCurvePointToAidl(
-        const std::string& xsdcCurvePoint) {
-    AudioHalVolumeCurve::CurvePoint aidlCurvePoint{};
-    if (sscanf(xsdcCurvePoint.c_str(), "%" SCNd8 ",%d", &aidlCurvePoint.index,
-               &aidlCurvePoint.attenuationMb) != 2) {
-        aidlCurvePoint.index = kInvalidCurvePointIndex;
-    }
-    return aidlCurvePoint;
-}
-
-AudioHalVolumeCurve EngineConfigXmlConverter::convertVolumeCurveToAidl(
-        const xsd::Volume& xsdcVolumeCurve) {
+ConversionResult<AudioHalVolumeCurve> EngineConfigXmlConverter::convertVolumeCurveToAidl(
+        const eng_xsd::Volume& xsdcVolumeCurve) {
     AudioHalVolumeCurve aidlVolumeCurve;
     aidlVolumeCurve.deviceCategory =
             static_cast<AudioHalVolumeCurve::DeviceCategory>(xsdcVolumeCurve.getDeviceCategory());
     if (xsdcVolumeCurve.hasRef()) {
         if (mVolumesReferenceMap.empty()) {
-            mVolumesReferenceMap = generateReferenceMap<xsd::VolumesType, xsd::VolumeRef>(
+            mVolumesReferenceMap = generateReferenceMap<eng_xsd::VolumesType, eng_xsd::VolumeRef>(
                     getXsdcConfig()->getVolumes());
         }
-        aidlVolumeCurve.curvePoints =
-                convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
+        aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
+                (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
                         mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
-                        std::bind(&EngineConfigXmlConverter::convertCurvePointToAidl, this,
-                                  std::placeholders::_1));
+                        &convertCurvePointToAidl)));
     } else {
-        aidlVolumeCurve.curvePoints =
-                convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
-                        xsdcVolumeCurve.getPoint(),
-                        std::bind(&EngineConfigXmlConverter::convertCurvePointToAidl, this,
-                                  std::placeholders::_1));
+        aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
+                (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+                        xsdcVolumeCurve.getPoint(), &convertCurvePointToAidl)));
     }
     return aidlVolumeCurve;
 }
 
-AudioHalVolumeGroup EngineConfigXmlConverter::convertVolumeGroupToAidl(
-        const xsd::VolumeGroupsType::VolumeGroup& xsdcVolumeGroup) {
+ConversionResult<AudioHalVolumeGroup> EngineConfigXmlConverter::convertVolumeGroupToAidl(
+        const eng_xsd::VolumeGroupsType::VolumeGroup& xsdcVolumeGroup) {
     AudioHalVolumeGroup aidlVolumeGroup;
     aidlVolumeGroup.name = xsdcVolumeGroup.getName();
     aidlVolumeGroup.minIndex = xsdcVolumeGroup.getIndexMin();
     aidlVolumeGroup.maxIndex = xsdcVolumeGroup.getIndexMax();
     aidlVolumeGroup.volumeCurves =
-            convertCollectionToAidlUnchecked<xsd::Volume, AudioHalVolumeCurve>(
+            VALUE_OR_FATAL((convertCollectionToAidl<eng_xsd::Volume, AudioHalVolumeCurve>(
                     xsdcVolumeGroup.getVolume(),
                     std::bind(&EngineConfigXmlConverter::convertVolumeCurveToAidl, this,
-                              std::placeholders::_1));
+                              std::placeholders::_1))));
     return aidlVolumeGroup;
 }
 
-AudioHalCapCriterion EngineConfigXmlConverter::convertCapCriterionToAidl(
-        const xsd::CriterionType& xsdcCriterion) {
-    AudioHalCapCriterion aidlCapCriterion;
-    aidlCapCriterion.name = xsdcCriterion.getName();
-    aidlCapCriterion.criterionTypeName = xsdcCriterion.getType();
-    aidlCapCriterion.defaultLiteralValue = xsdcCriterion.get_default();
-    return aidlCapCriterion;
-}
-
-std::string EngineConfigXmlConverter::convertCriterionTypeValueToAidl(
-        const xsd::ValueType& xsdcCriterionTypeValue) {
-    return xsdcCriterionTypeValue.getLiteral();
-}
-
-AudioHalCapCriterionType EngineConfigXmlConverter::convertCapCriterionTypeToAidl(
-        const xsd::CriterionTypeType& xsdcCriterionType) {
-    AudioHalCapCriterionType aidlCapCriterionType;
-    aidlCapCriterionType.name = xsdcCriterionType.getName();
-    aidlCapCriterionType.isInclusive = !(static_cast<bool>(xsdcCriterionType.getType()));
-    aidlCapCriterionType.values =
-            convertWrappedCollectionToAidlUnchecked<xsd::ValuesType, xsd::ValueType, std::string>(
-                    xsdcCriterionType.getValues(), &xsd::ValuesType::getValue,
-                    std::bind(&EngineConfigXmlConverter::convertCriterionTypeValueToAidl, this,
-                              std::placeholders::_1));
-    return aidlCapCriterionType;
-}
-
 AudioHalEngineConfig& EngineConfigXmlConverter::getAidlEngineConfig() {
     return mAidlEngineConfig;
 }
@@ -266,39 +223,42 @@
 void EngineConfigXmlConverter::init() {
     initProductStrategyMap();
     if (getXsdcConfig()->hasProductStrategies()) {
-        mAidlEngineConfig.productStrategies =
-                convertWrappedCollectionToAidlUnchecked<xsd::ProductStrategies,
-                                                        xsd::ProductStrategies::ProductStrategy,
-                                                        AudioHalProductStrategy>(
+        mAidlEngineConfig.productStrategies = VALUE_OR_FATAL(
+                (convertWrappedCollectionToAidl<eng_xsd::ProductStrategies,
+                                                eng_xsd::ProductStrategies::ProductStrategy,
+                                                AudioHalProductStrategy>(
                         getXsdcConfig()->getProductStrategies(),
-                        &xsd::ProductStrategies::getProductStrategy,
+                        &eng_xsd::ProductStrategies::getProductStrategy,
                         std::bind(&EngineConfigXmlConverter::convertProductStrategyToAidl, this,
-                                  std::placeholders::_1));
+                                  std::placeholders::_1))));
         if (mDefaultProductStrategyId) {
             mAidlEngineConfig.defaultProductStrategyId = mDefaultProductStrategyId.value();
         }
     }
     if (getXsdcConfig()->hasVolumeGroups()) {
-        mAidlEngineConfig.volumeGroups = convertWrappedCollectionToAidlUnchecked<
-                xsd::VolumeGroupsType, xsd::VolumeGroupsType::VolumeGroup, AudioHalVolumeGroup>(
-                getXsdcConfig()->getVolumeGroups(), &xsd::VolumeGroupsType::getVolumeGroup,
-                std::bind(&EngineConfigXmlConverter::convertVolumeGroupToAidl, this,
-                          std::placeholders::_1));
+        mAidlEngineConfig.volumeGroups = VALUE_OR_FATAL(
+                (convertWrappedCollectionToAidl<eng_xsd::VolumeGroupsType,
+                                                eng_xsd::VolumeGroupsType::VolumeGroup,
+                                                AudioHalVolumeGroup>(
+                        getXsdcConfig()->getVolumeGroups(),
+                        &eng_xsd::VolumeGroupsType::getVolumeGroup,
+                        std::bind(&EngineConfigXmlConverter::convertVolumeGroupToAidl, this,
+                                  std::placeholders::_1))));
     }
     if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) {
         AudioHalEngineConfig::CapSpecificConfig capSpecificConfig;
-        capSpecificConfig.criteria =
-                convertWrappedCollectionToAidlUnchecked<xsd::CriteriaType, xsd::CriterionType,
-                                                        AudioHalCapCriterion>(
-                        getXsdcConfig()->getCriteria(), &xsd::CriteriaType::getCriterion,
-                        std::bind(&EngineConfigXmlConverter::convertCapCriterionToAidl, this,
-                                  std::placeholders::_1));
-        capSpecificConfig.criterionTypes = convertWrappedCollectionToAidlUnchecked<
-                xsd::CriterionTypesType, xsd::CriterionTypeType, AudioHalCapCriterionType>(
-                getXsdcConfig()->getCriterion_types(), &xsd::CriterionTypesType::getCriterion_type,
-                std::bind(&EngineConfigXmlConverter::convertCapCriterionTypeToAidl, this,
-                          std::placeholders::_1));
-        mAidlEngineConfig.capSpecificConfig = capSpecificConfig;
+        capSpecificConfig.criteria = VALUE_OR_FATAL(
+                (convertWrappedCollectionToAidl<eng_xsd::CriteriaType, eng_xsd::CriterionType,
+                                                AudioHalCapCriterion>(
+                        getXsdcConfig()->getCriteria(), &eng_xsd::CriteriaType::getCriterion,
+                        &convertCapCriterionToAidl)));
+        capSpecificConfig.criterionTypes =
+                VALUE_OR_FATAL((convertWrappedCollectionToAidl<eng_xsd::CriterionTypesType,
+                                                               eng_xsd::CriterionTypeType,
+                                                               AudioHalCapCriterionType>(
+                        getXsdcConfig()->getCriterion_types(),
+                        &eng_xsd::CriterionTypesType::getCriterion_type,
+                        &convertCapCriterionTypeToAidl)));
     }
 }
 }  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 76132b3..1045009 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -25,6 +25,7 @@
 #include <android/binder_ibinder_platform.h>
 #include <error/expected_utils.h>
 
+#include "core-impl/Configuration.h"
 #include "core-impl/Module.h"
 #include "core-impl/ModuleBluetooth.h"
 #include "core-impl/ModulePrimary.h"
@@ -42,6 +43,7 @@
 using aidl::android::hardware::audio::core::sounddose::ISoundDose;
 using aidl::android::media::audio::common::AudioChannelLayout;
 using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceType;
 using aidl::android::media::audio::common::AudioFormatDescription;
 using aidl::android::media::audio::common::AudioFormatType;
 using aidl::android::media::audio::common::AudioInputFlags;
@@ -65,32 +67,56 @@
 
 namespace {
 
+inline bool hasDynamicChannelMasks(const std::vector<AudioChannelLayout>& channelMasks) {
+    return channelMasks.empty() ||
+           std::all_of(channelMasks.begin(), channelMasks.end(),
+                       [](const auto& channelMask) { return channelMask == AudioChannelLayout{}; });
+}
+
+inline bool hasDynamicFormat(const AudioFormatDescription& format) {
+    return format == AudioFormatDescription{};
+}
+
+inline bool hasDynamicSampleRates(const std::vector<int32_t>& sampleRates) {
+    return sampleRates.empty() ||
+           std::all_of(sampleRates.begin(), sampleRates.end(),
+                       [](const auto& sampleRate) { return sampleRate == 0; });
+}
+
+inline bool isDynamicProfile(const AudioProfile& profile) {
+    return hasDynamicFormat(profile.format) || hasDynamicChannelMasks(profile.channelMasks) ||
+           hasDynamicSampleRates(profile.sampleRates);
+}
+
+bool hasDynamicProfilesOnly(const std::vector<AudioProfile>& profiles) {
+    if (profiles.empty()) return true;
+    return std::all_of(profiles.begin(), profiles.end(), isDynamicProfile);
+}
+
+// Note: does not assign an ID to the config.
 bool generateDefaultPortConfig(const AudioPort& port, AudioPortConfig* config) {
+    const bool allowDynamicConfig = port.ext.getTag() == AudioPortExt::device;
     *config = {};
     config->portId = port.id;
-    if (port.profiles.empty()) {
-        LOG(ERROR) << __func__ << ": port " << port.id << " has no profiles";
-        return false;
+    for (const auto& profile : port.profiles) {
+        if (isDynamicProfile(profile)) continue;
+        config->format = profile.format;
+        config->channelMask = *profile.channelMasks.begin();
+        config->sampleRate = Int{.value = *profile.sampleRates.begin()};
+        config->flags = port.flags;
+        config->ext = port.ext;
+        return true;
     }
-    const auto& profile = port.profiles.begin();
-    config->format = profile->format;
-    if (profile->channelMasks.empty()) {
-        LOG(ERROR) << __func__ << ": the first profile in port " << port.id
-                   << " has no channel masks";
-        return false;
+    if (allowDynamicConfig) {
+        config->format = AudioFormatDescription{};
+        config->channelMask = AudioChannelLayout{};
+        config->sampleRate = Int{.value = 0};
+        config->flags = port.flags;
+        config->ext = port.ext;
+        return true;
     }
-    config->channelMask = *profile->channelMasks.begin();
-    if (profile->sampleRates.empty()) {
-        LOG(ERROR) << __func__ << ": the first profile in port " << port.id
-                   << " has no sample rates";
-        return false;
-    }
-    Int sampleRate;
-    sampleRate.value = *profile->sampleRates.begin();
-    config->sampleRate = sampleRate;
-    config->flags = port.flags;
-    config->ext = port.ext;
-    return true;
+    LOG(ERROR) << __func__ << ": port " << port.id << " only has dynamic profiles";
+    return false;
 }
 
 bool findAudioProfile(const AudioPort& port, const AudioFormatDescription& format,
@@ -108,21 +134,36 @@
 }  // namespace
 
 // static
-std::shared_ptr<Module> Module::createInstance(Type type) {
+std::shared_ptr<Module> Module::createInstance(Type type, std::unique_ptr<Configuration>&& config) {
     switch (type) {
         case Type::DEFAULT:
-            return ndk::SharedRefBase::make<ModulePrimary>();
+            return ndk::SharedRefBase::make<ModulePrimary>(std::move(config));
         case Type::R_SUBMIX:
-            return ndk::SharedRefBase::make<ModuleRemoteSubmix>();
+            return ndk::SharedRefBase::make<ModuleRemoteSubmix>(std::move(config));
         case Type::STUB:
-            return ndk::SharedRefBase::make<ModuleStub>();
+            return ndk::SharedRefBase::make<ModuleStub>(std::move(config));
         case Type::USB:
-            return ndk::SharedRefBase::make<ModuleUsb>();
+            return ndk::SharedRefBase::make<ModuleUsb>(std::move(config));
         case Type::BLUETOOTH:
-            return ndk::SharedRefBase::make<ModuleBluetooth>();
+            return ndk::SharedRefBase::make<ModuleBluetooth>(std::move(config));
     }
 }
 
+// static
+std::optional<Module::Type> Module::typeFromString(const std::string& type) {
+    if (type == "default")
+        return Module::Type::DEFAULT;
+    else if (type == "r_submix")
+        return Module::Type::R_SUBMIX;
+    else if (type == "stub")
+        return Module::Type::STUB;
+    else if (type == "usb")
+        return Module::Type::USB;
+    else if (type == "bluetooth")
+        return Module::Type::BLUETOOTH;
+    return {};
+}
+
 std::ostream& operator<<(std::ostream& os, Module::Type t) {
     switch (t) {
         case Module::Type::DEFAULT:
@@ -144,6 +185,11 @@
     return os;
 }
 
+Module::Module(Type type, std::unique_ptr<Configuration>&& config)
+    : mType(type), mConfig(std::move(config)) {
+    populateConnectedProfiles();
+}
+
 void Module::cleanUpPatch(int32_t patchId) {
     erase_all_values(mPatches, std::set<int32_t>{patchId});
 }
@@ -279,6 +325,22 @@
     return ndk::ScopedAStatus::ok();
 }
 
+void Module::populateConnectedProfiles() {
+    Configuration& config = getConfig();
+    for (const AudioPort& port : config.ports) {
+        if (port.ext.getTag() == AudioPortExt::device) {
+            if (auto devicePort = port.ext.get<AudioPortExt::device>();
+                !devicePort.device.type.connection.empty() && port.profiles.empty()) {
+                if (auto connIt = config.connectedProfiles.find(port.id);
+                    connIt == config.connectedProfiles.end()) {
+                    config.connectedProfiles.emplace(
+                            port.id, internal::getStandard16And24BitPcmAudioProfiles());
+                }
+            }
+        }
+    }
+}
+
 template <typename C>
 std::set<int32_t> Module::portIdsFromPortConfigIds(C portConfigIds) {
     std::set<int32_t> result;
@@ -292,35 +354,47 @@
     return result;
 }
 
-std::unique_ptr<internal::Configuration> Module::initializeConfig() {
-    std::unique_ptr<internal::Configuration> config;
-    switch (getType()) {
-        case Type::DEFAULT:
-            config = std::move(internal::getPrimaryConfiguration());
-            break;
-        case Type::R_SUBMIX:
-            config = std::move(internal::getRSubmixConfiguration());
-            break;
-        case Type::STUB:
-            config = std::move(internal::getStubConfiguration());
-            break;
-        case Type::USB:
-            config = std::move(internal::getUsbConfiguration());
-            break;
-        case Type::BLUETOOTH:
-            config = std::move(internal::getBluetoothConfiguration());
-            break;
-    }
-    return config;
+std::unique_ptr<Module::Configuration> Module::initializeConfig() {
+    return internal::getConfiguration(getType());
 }
 
-internal::Configuration& Module::getConfig() {
+std::vector<AudioRoute*> Module::getAudioRoutesForAudioPortImpl(int32_t portId) {
+    std::vector<AudioRoute*> result;
+    auto& routes = getConfig().routes;
+    for (auto& r : routes) {
+        const auto& srcs = r.sourcePortIds;
+        if (r.sinkPortId == portId || std::find(srcs.begin(), srcs.end(), portId) != srcs.end()) {
+            result.push_back(&r);
+        }
+    }
+    return result;
+}
+
+Module::Configuration& Module::getConfig() {
     if (!mConfig) {
         mConfig = std::move(initializeConfig());
     }
     return *mConfig;
 }
 
+std::set<int32_t> Module::getRoutableAudioPortIds(int32_t portId,
+                                                  std::vector<AudioRoute*>* routes) {
+    std::vector<AudioRoute*> routesStorage;
+    if (routes == nullptr) {
+        routesStorage = getAudioRoutesForAudioPortImpl(portId);
+        routes = &routesStorage;
+    }
+    std::set<int32_t> result;
+    for (AudioRoute* r : *routes) {
+        if (r->sinkPortId == portId) {
+            result.insert(r->sourcePortIds.begin(), r->sourcePortIds.end());
+        } else {
+            result.insert(r->sinkPortId);
+        }
+    }
+    return result;
+}
+
 void Module::registerPatch(const AudioPatch& patch) {
     auto& configs = getConfig().portConfigs;
     auto do_insert = [&](const std::vector<int32_t>& portConfigIds) {
@@ -510,7 +584,31 @@
         }
     }
 
-    if (connectedPort.profiles.empty()) {
+    // Two main cases are considered with regard to the profiles of the connected device port:
+    //
+    //  1. If the template device port has dynamic profiles, and at least one routable mix
+    //     port also has dynamic profiles, it means that after connecting the device, the
+    //     connected device port must have profiles populated with actual capabilities of
+    //     the connected device, and dynamic of routable mix ports will be filled
+    //     according to these capabilities. An example of this case is connection of an
+    //     HDMI or USB device. For USB handled by ADSP, there can be mix ports with static
+    //     profiles, and one dedicated mix port for "hi-fi" playback. The latter is left with
+    //     dynamic profiles so that they can be populated with actual capabilities of
+    //     the connected device.
+    //
+    //  2. If the template device port has dynamic profiles, while all routable mix ports
+    //     have static profiles, it means that after connecting the device, the connected
+    //     device port can be left with dynamic profiles, and profiles of mix ports are
+    //     left untouched. An example of this case is connection of an analog wired
+    //     headset, it should be treated in the same way as a speaker.
+    //
+    //  Yet another possible case is when both the template device port and all routable
+    //  mix ports have static profiles. This is allowed and handled correctly, however, it
+    //  is not very practical, since these profiles are likely duplicates of each other.
+
+    std::vector<AudioRoute*> routesToMixPorts = getAudioRoutesForAudioPortImpl(templateId);
+    std::set<int32_t> routableMixPortIds = getRoutableAudioPortIds(templateId, &routesToMixPorts);
+    if (hasDynamicProfilesOnly(connectedPort.profiles)) {
         if (!mDebug.simulateDeviceConnections) {
             RETURN_STATUS_IF_ERROR(populateConnectedDevicePort(&connectedPort));
         } else {
@@ -520,23 +618,22 @@
                 connectedPort.profiles = connectedProfilesIt->second;
             }
         }
-        if (connectedPort.profiles.empty()) {
-            LOG(ERROR) << __func__
-                       << ": profiles of a connected port still empty after connecting external "
-                          "device "
-                       << connectedPort.toString();
-            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-        }
-    }
-
-    for (auto profile : connectedPort.profiles) {
-        if (profile.channelMasks.empty()) {
-            LOG(ERROR) << __func__ << ": the profile " << profile.name << " has no channel masks";
-            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-        }
-        if (profile.sampleRates.empty()) {
-            LOG(ERROR) << __func__ << ": the profile " << profile.name << " has no sample rates";
-            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        if (hasDynamicProfilesOnly(connectedPort.profiles)) {
+            // Possible case 2. Check if all routable mix ports have static profiles.
+            if (auto dynamicMixPortIt = std::find_if(ports.begin(), ports.end(),
+                                                     [&routableMixPortIds](const auto& p) {
+                                                         return routableMixPortIds.count(p.id) >
+                                                                        0 &&
+                                                                hasDynamicProfilesOnly(p.profiles);
+                                                     });
+                dynamicMixPortIt != ports.end()) {
+                LOG(ERROR) << __func__
+                           << ": connected port only has dynamic profiles after connecting "
+                           << "external device " << connectedPort.toString() << ", and there exist "
+                           << "a routable mix port with dynamic profiles: "
+                           << dynamicMixPortIt->toString();
+                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+            }
         }
     }
 
@@ -548,44 +645,36 @@
     ports.push_back(connectedPort);
     onExternalDeviceConnectionChanged(connectedPort, true /*connected*/);
 
-    std::vector<int32_t> routablePortIds;
+    // For routes where the template port is a source, add the connected port to sources,
+    // otherwise, create a new route by copying from the route for the template port.
     std::vector<AudioRoute> newRoutes;
-    auto& routes = getConfig().routes;
-    for (auto& r : routes) {
-        if (r.sinkPortId == templateId) {
-            AudioRoute newRoute;
-            newRoute.sourcePortIds = r.sourcePortIds;
-            newRoute.sinkPortId = connectedPort.id;
-            newRoute.isExclusive = r.isExclusive;
-            newRoutes.push_back(std::move(newRoute));
-            routablePortIds.insert(routablePortIds.end(), r.sourcePortIds.begin(),
-                                   r.sourcePortIds.end());
+    for (AudioRoute* r : routesToMixPorts) {
+        if (r->sinkPortId == templateId) {
+            newRoutes.push_back(AudioRoute{.sourcePortIds = r->sourcePortIds,
+                                           .sinkPortId = connectedPort.id,
+                                           .isExclusive = r->isExclusive});
         } else {
-            auto& srcs = r.sourcePortIds;
-            if (std::find(srcs.begin(), srcs.end(), templateId) != srcs.end()) {
-                srcs.push_back(connectedPort.id);
-                routablePortIds.push_back(r.sinkPortId);
-            }
+            r->sourcePortIds.push_back(connectedPort.id);
         }
     }
+    auto& routes = getConfig().routes;
     routes.insert(routes.end(), newRoutes.begin(), newRoutes.end());
 
-    // Note: this is a simplistic approach assuming that a mix port can only be populated
-    // from a single device port. Implementing support for stuffing dynamic profiles with a superset
-    // of all profiles from all routable dynamic device ports would be more involved.
-    for (const auto mixPortId : routablePortIds) {
-        auto portsIt = findById<AudioPort>(ports, mixPortId);
-        if (portsIt != ports.end()) {
-            if (portsIt->profiles.empty()) {
-                portsIt->profiles = connectedPort.profiles;
-                connectedPortsIt->second.insert(portsIt->id);
+    if (!hasDynamicProfilesOnly(connectedPort.profiles) && !routableMixPortIds.empty()) {
+        // Note: this is a simplistic approach assuming that a mix port can only be populated
+        // from a single device port. Implementing support for stuffing dynamic profiles with
+        // a superset of all profiles from all routable dynamic device ports would be more involved.
+        for (auto& port : ports) {
+            if (routableMixPortIds.count(port.id) == 0) continue;
+            if (hasDynamicProfilesOnly(port.profiles)) {
+                port.profiles = connectedPort.profiles;
+                connectedPortsIt->second.insert(port.id);
             } else {
-                // Check if profiles are non empty because they were populated by
-                // a previous connection. Otherwise, it means that they are not empty because
-                // the mix port has static profiles.
-                for (const auto cp : mConnectedDevicePorts) {
-                    if (cp.second.count(portsIt->id) > 0) {
-                        connectedPortsIt->second.insert(portsIt->id);
+                // Check if profiles are not all dynamic because they were populated by
+                // a previous connection. Otherwise, it means that they are actually static.
+                for (const auto& cp : mConnectedDevicePorts) {
+                    if (cp.second.count(port.id) > 0) {
+                        connectedPortsIt->second.insert(port.id);
                         break;
                     }
                 }
@@ -705,13 +794,9 @@
         LOG(ERROR) << __func__ << ": port id " << in_portId << " not found";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
-    auto& routes = getConfig().routes;
-    std::copy_if(routes.begin(), routes.end(), std::back_inserter(*_aidl_return),
-                 [&](const auto& r) {
-                     const auto& srcs = r.sourcePortIds;
-                     return r.sinkPortId == in_portId ||
-                            std::find(srcs.begin(), srcs.end(), in_portId) != srcs.end();
-                 });
+    std::vector<AudioRoute*> routes = getAudioRoutesForAudioPortImpl(in_portId);
+    std::transform(routes.begin(), routes.end(), std::back_inserter(*_aidl_return),
+                   [](auto rptr) { return *rptr; });
     return ndk::ScopedAStatus::ok();
 }
 
@@ -732,7 +817,7 @@
     context.fillDescriptor(&_aidl_return->desc);
     std::shared_ptr<StreamIn> stream;
     RETURN_STATUS_IF_ERROR(createInputStream(std::move(context), in_args.sinkMetadata,
-                                             mConfig->microphones, &stream));
+                                             getMicrophoneInfos(), &stream));
     StreamWrapper streamWrapper(stream);
     if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {
         RETURN_STATUS_IF_ERROR(
@@ -925,13 +1010,14 @@
 
     const int portId = existing != configs.end() ? existing->portId : in_requested.portId;
     if (portId == 0) {
-        LOG(ERROR) << __func__ << ": input port config does not specify portId";
+        LOG(ERROR) << __func__ << ": requested port config does not specify portId";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     auto& ports = getConfig().ports;
     auto portIt = findById<AudioPort>(ports, portId);
     if (portIt == ports.end()) {
-        LOG(ERROR) << __func__ << ": input port config points to non-existent portId " << portId;
+        LOG(ERROR) << __func__ << ": requested port config points to non-existent portId "
+                   << portId;
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     if (existing != configs.end()) {
@@ -949,6 +1035,10 @@
     // or a new generated config. Now attempt to update it according to the specified
     // fields of 'in_requested'.
 
+    // Device ports with only dynamic profiles are used for devices that are connected via ADSP,
+    // which takes care of their actual configuration automatically.
+    const bool allowDynamicConfig = portIt->ext.getTag() == AudioPortExt::device &&
+                                    hasDynamicProfilesOnly(portIt->profiles);
     bool requestedIsValid = true, requestedIsFullySpecified = true;
 
     AudioIoFlags portFlags = portIt->flags;
@@ -966,17 +1056,19 @@
     AudioProfile portProfile;
     if (in_requested.format.has_value()) {
         const auto& format = in_requested.format.value();
-        if (findAudioProfile(*portIt, format, &portProfile)) {
+        if ((format == AudioFormatDescription{} && allowDynamicConfig) ||
+            findAudioProfile(*portIt, format, &portProfile)) {
             out_suggested->format = format;
         } else {
             LOG(WARNING) << __func__ << ": requested format " << format.toString()
-                         << " is not found in port's " << portId << " profiles";
+                         << " is not found in the profiles of port " << portId;
             requestedIsValid = false;
         }
     } else {
         requestedIsFullySpecified = false;
     }
-    if (!findAudioProfile(*portIt, out_suggested->format.value(), &portProfile)) {
+    if (!(out_suggested->format.value() == AudioFormatDescription{} && allowDynamicConfig) &&
+        !findAudioProfile(*portIt, out_suggested->format.value(), &portProfile)) {
         LOG(ERROR) << __func__ << ": port " << portId << " does not support format "
                    << out_suggested->format.value().toString() << " anymore";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
@@ -984,8 +1076,9 @@
 
     if (in_requested.channelMask.has_value()) {
         const auto& channelMask = in_requested.channelMask.value();
-        if (find(portProfile.channelMasks.begin(), portProfile.channelMasks.end(), channelMask) !=
-            portProfile.channelMasks.end()) {
+        if ((channelMask == AudioChannelLayout{} && allowDynamicConfig) ||
+            find(portProfile.channelMasks.begin(), portProfile.channelMasks.end(), channelMask) !=
+                    portProfile.channelMasks.end()) {
             out_suggested->channelMask = channelMask;
         } else {
             LOG(WARNING) << __func__ << ": requested channel mask " << channelMask.toString()
@@ -999,7 +1092,8 @@
 
     if (in_requested.sampleRate.has_value()) {
         const auto& sampleRate = in_requested.sampleRate.value();
-        if (find(portProfile.sampleRates.begin(), portProfile.sampleRates.end(),
+        if ((sampleRate.value == 0 && allowDynamicConfig) ||
+            find(portProfile.sampleRates.begin(), portProfile.sampleRates.end(),
                  sampleRate.value) != portProfile.sampleRates.end()) {
             out_suggested->sampleRate = sampleRate;
         } else {
@@ -1157,7 +1251,7 @@
 }
 
 ndk::ScopedAStatus Module::getMicrophones(std::vector<MicrophoneInfo>* _aidl_return) {
-    *_aidl_return = getConfig().microphones;
+    *_aidl_return = getMicrophoneInfos();
     LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
     return ndk::ScopedAStatus::ok();
 }
@@ -1397,7 +1491,18 @@
     return mIsMmapSupported.value();
 }
 
-ndk::ScopedAStatus Module::populateConnectedDevicePort(AudioPort* audioPort __unused) {
+ndk::ScopedAStatus Module::populateConnectedDevicePort(AudioPort* audioPort) {
+    if (audioPort->ext.getTag() != AudioPortExt::device) {
+        LOG(ERROR) << __func__ << ": not a device port: " << audioPort->toString();
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    const auto& devicePort = audioPort->ext.get<AudioPortExt::device>();
+    if (!devicePort.device.type.connection.empty()) {
+        LOG(ERROR) << __func__
+                   << ": module implementation must override 'populateConnectedDevicePort' "
+                   << "to handle connection of external devices.";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
     LOG(VERBOSE) << __func__ << ": do nothing and return ok";
     return ndk::ScopedAStatus::ok();
 }
@@ -1425,6 +1530,29 @@
     return ndk::ScopedAStatus::ok();
 }
 
+std::vector<MicrophoneInfo> Module::getMicrophoneInfos() {
+    std::vector<MicrophoneInfo> result;
+    Configuration& config = getConfig();
+    for (const AudioPort& port : config.ports) {
+        if (port.ext.getTag() == AudioPortExt::Tag::device) {
+            const AudioDeviceType deviceType =
+                    port.ext.get<AudioPortExt::Tag::device>().device.type.type;
+            if (deviceType == AudioDeviceType::IN_MICROPHONE ||
+                deviceType == AudioDeviceType::IN_MICROPHONE_BACK) {
+                // Placeholder values. Vendor implementations must populate MicrophoneInfo
+                // accordingly based on their physical microphone parameters.
+                result.push_back(MicrophoneInfo{
+                        .id = port.name,
+                        .device = port.ext.get<AudioPortExt::Tag::device>().device,
+                        .group = 0,
+                        .indexInTheGroup = 0,
+                });
+            }
+        }
+    }
+    return result;
+}
+
 Module::BtProfileHandles Module::getBtProfileManagerHandles() {
     return std::make_tuple(std::weak_ptr<IBluetooth>(), std::weak_ptr<IBluetoothA2dp>(),
                            std::weak_ptr<IBluetoothLe>());
diff --git a/audio/aidl/default/Telephony.cpp b/audio/aidl/default/Telephony.cpp
index bf05a8d..d9da39f 100644
--- a/audio/aidl/default/Telephony.cpp
+++ b/audio/aidl/default/Telephony.cpp
@@ -16,9 +16,9 @@
 
 #define LOG_TAG "AHAL_Telephony"
 #include <android-base/logging.h>
+#include <android/binder_to_string.h>
 
 #include <Utils.h>
-#include <android/binder_to_string.h>
 
 #include "core-impl/Telephony.h"
 
diff --git a/audio/aidl/default/XsdcConversion.cpp b/audio/aidl/default/XsdcConversion.cpp
new file mode 100644
index 0000000..9e30347
--- /dev/null
+++ b/audio/aidl/default/XsdcConversion.cpp
@@ -0,0 +1,448 @@
+#include <inttypes.h>
+
+#include <unordered_set>
+
+#define LOG_TAG "AHAL_Config"
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+
+#include <aidl/android/media/audio/common/AudioPort.h>
+#include <aidl/android/media/audio/common/AudioPortConfig.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/TypeConverter.h>
+
+#include "core-impl/XmlConverter.h"
+#include "core-impl/XsdcConversion.h"
+
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioGain;
+using aidl::android::media::audio::common::AudioHalCapCriterion;
+using aidl::android::media::audio::common::AudioHalCapCriterionType;
+using aidl::android::media::audio::common::AudioHalVolumeCurve;
+using aidl::android::media::audio::common::AudioIoFlags;
+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::AudioPortMixExt;
+using aidl::android::media::audio::common::AudioProfile;
+using ::android::BAD_VALUE;
+using ::android::base::unexpected;
+
+namespace ap_xsd = android::audio::policy::configuration;
+namespace eng_xsd = android::audio::policy::engine::configuration;
+
+namespace aidl::android::hardware::audio::core::internal {
+
+inline ConversionResult<std::string> assertNonEmpty(const std::string& s) {
+    if (s.empty()) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config: "
+                   << " empty string is not valid.";
+        return unexpected(BAD_VALUE);
+    }
+    return s;
+}
+
+#define NON_EMPTY_STRING_OR_FATAL(s) VALUE_OR_FATAL(assertNonEmpty(s))
+
+ConversionResult<AudioFormatDescription> convertAudioFormatToAidl(const std::string& xsdcFormat) {
+    audio_format_t legacyFormat = ::android::formatFromString(xsdcFormat, AUDIO_FORMAT_DEFAULT);
+    ConversionResult<AudioFormatDescription> result =
+            legacy2aidl_audio_format_t_AudioFormatDescription(legacyFormat);
+    if ((legacyFormat == AUDIO_FORMAT_DEFAULT && xsdcFormat.compare("AUDIO_FORMAT_DEFAULT") != 0) ||
+        !result.ok()) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config: " << xsdcFormat
+                   << " is not a valid audio format.";
+        return unexpected(BAD_VALUE);
+    }
+    return result;
+}
+
+std::unordered_set<std::string> getAttachedDevices(const ap_xsd::Modules::Module& moduleConfig) {
+    std::unordered_set<std::string> attachedDeviceSet;
+    if (moduleConfig.hasAttachedDevices()) {
+        for (const ap_xsd::AttachedDevices& attachedDevices : moduleConfig.getAttachedDevices()) {
+            if (attachedDevices.hasItem()) {
+                attachedDeviceSet.insert(attachedDevices.getItem().begin(),
+                                         attachedDevices.getItem().end());
+            }
+        }
+    }
+    return attachedDeviceSet;
+}
+
+ConversionResult<AudioDeviceDescription> convertDeviceTypeToAidl(const std::string& xType) {
+    audio_devices_t legacyDeviceType = AUDIO_DEVICE_NONE;
+    ::android::DeviceConverter::fromString(xType, legacyDeviceType);
+    ConversionResult<AudioDeviceDescription> result =
+            legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyDeviceType);
+    if ((legacyDeviceType == AUDIO_DEVICE_NONE) || !result.ok()) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config: " << xType
+                   << " is not a valid device type.";
+        return unexpected(BAD_VALUE);
+    }
+    return result;
+}
+
+ConversionResult<AudioDevice> createAudioDevice(
+        const ap_xsd::DevicePorts::DevicePort& xDevicePort) {
+    AudioDevice device = {
+            .type = VALUE_OR_FATAL(convertDeviceTypeToAidl(xDevicePort.getType())),
+            .address = xDevicePort.hasAddress()
+                               ? AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(
+                                         xDevicePort.getAddress())
+                               : AudioDeviceAddress{}};
+    if (device.type.type == AudioDeviceType::IN_MICROPHONE && device.type.connection.empty()) {
+        device.address = "bottom";
+    } else if (device.type.type == AudioDeviceType::IN_MICROPHONE_BACK &&
+               device.type.connection.empty()) {
+        device.address = "back";
+    }
+    return device;
+}
+
+ConversionResult<AudioPortExt> createAudioPortExt(
+        const ap_xsd::DevicePorts::DevicePort& xDevicePort,
+        const std::string& xDefaultOutputDevice) {
+    AudioPortDeviceExt deviceExt = {
+            .device = VALUE_OR_FATAL(createAudioDevice(xDevicePort)),
+            .flags = (xDevicePort.getTagName() == xDefaultOutputDevice)
+                             ? 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE
+                             : 0,
+            .encodedFormats =
+                    xDevicePort.hasEncodedFormats()
+                            ? VALUE_OR_FATAL(
+                                      (convertCollectionToAidl<std::string, AudioFormatDescription>(
+                                              xDevicePort.getEncodedFormats(),
+                                              &convertAudioFormatToAidl)))
+                            : std::vector<AudioFormatDescription>{},
+    };
+    return AudioPortExt::make<AudioPortExt::Tag::device>(deviceExt);
+}
+
+ConversionResult<AudioPortExt> createAudioPortExt(const ap_xsd::MixPorts::MixPort& xMixPort) {
+    AudioPortMixExt mixExt = {
+            .maxOpenStreamCount =
+                    xMixPort.hasMaxOpenCount() ? static_cast<int>(xMixPort.getMaxOpenCount()) : 0,
+            .maxActiveStreamCount = xMixPort.hasMaxActiveCount()
+                                            ? static_cast<int>(xMixPort.getMaxActiveCount())
+                                            : 1,
+            .recommendedMuteDurationMs =
+                    xMixPort.hasRecommendedMuteDurationMs()
+                            ? static_cast<int>(xMixPort.getRecommendedMuteDurationMs())
+                            : 0};
+    return AudioPortExt::make<AudioPortExt::Tag::mix>(mixExt);
+}
+
+ConversionResult<int> convertGainModeToAidl(const std::vector<ap_xsd::AudioGainMode>& gainModeVec) {
+    int gainModeMask = 0;
+    for (const ap_xsd::AudioGainMode& gainMode : gainModeVec) {
+        audio_gain_mode_t legacyGainMode;
+        if (::android::GainModeConverter::fromString(ap_xsd::toString(gainMode), legacyGainMode)) {
+            gainModeMask |= static_cast<int>(legacyGainMode);
+        }
+    }
+    return gainModeMask;
+}
+
+ConversionResult<AudioChannelLayout> convertChannelMaskToAidl(
+        const ap_xsd::AudioChannelMask& xChannelMask) {
+    std::string xChannelMaskLiteral = ap_xsd::toString(xChannelMask);
+    audio_channel_mask_t legacyChannelMask = ::android::channelMaskFromString(xChannelMaskLiteral);
+    ConversionResult<AudioChannelLayout> result =
+            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                    legacyChannelMask,
+                    /* isInput= */ xChannelMaskLiteral.find("AUDIO_CHANNEL_IN_") == 0);
+    if ((legacyChannelMask == AUDIO_CHANNEL_INVALID) || !result.ok()) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config: " << xChannelMaskLiteral
+                   << " is not a valid audio channel mask.";
+        return unexpected(BAD_VALUE);
+    }
+    return result;
+}
+
+ConversionResult<AudioGain> convertGainToAidl(const ap_xsd::Gains::Gain& xGain) {
+    return AudioGain{
+            .mode = VALUE_OR_FATAL(convertGainModeToAidl(xGain.getMode())),
+            .channelMask =
+                    xGain.hasChannel_mask()
+                            ? VALUE_OR_FATAL(convertChannelMaskToAidl(xGain.getChannel_mask()))
+                            : AudioChannelLayout{},
+            .minValue = xGain.hasMinValueMB() ? xGain.getMinValueMB() : 0,
+            .maxValue = xGain.hasMaxValueMB() ? xGain.getMaxValueMB() : 0,
+            .defaultValue = xGain.hasDefaultValueMB() ? xGain.getDefaultValueMB() : 0,
+            .stepValue = xGain.hasStepValueMB() ? xGain.getStepValueMB() : 0,
+            .minRampMs = xGain.hasMinRampMs() ? xGain.getMinRampMs() : 0,
+            .maxRampMs = xGain.hasMaxRampMs() ? xGain.getMaxRampMs() : 0,
+            .useForVolume = xGain.hasUseForVolume() ? xGain.getUseForVolume() : false,
+    };
+}
+
+ConversionResult<AudioProfile> convertAudioProfileToAidl(const ap_xsd::Profile& xProfile) {
+    return AudioProfile{
+            .format = xProfile.hasFormat()
+                              ? VALUE_OR_FATAL(convertAudioFormatToAidl(xProfile.getFormat()))
+                              : AudioFormatDescription{},
+            .channelMasks =
+                    xProfile.hasChannelMasks()
+                            ? VALUE_OR_FATAL((convertCollectionToAidl<ap_xsd::AudioChannelMask,
+                                                                      AudioChannelLayout>(
+                                      xProfile.getChannelMasks(), &convertChannelMaskToAidl)))
+                            : std::vector<AudioChannelLayout>{},
+            .sampleRates = xProfile.hasSamplingRates()
+                                   ? VALUE_OR_FATAL((convertCollectionToAidl<int64_t, int>(
+                                             xProfile.getSamplingRates(),
+                                             [](const int64_t x) -> int { return x; })))
+                                   : std::vector<int>{}};
+}
+
+ConversionResult<AudioIoFlags> convertIoFlagsToAidl(
+        const std::vector<ap_xsd::AudioInOutFlag>& flags, const ap_xsd::Role role,
+        bool flagsForMixPort) {
+    int flagMask = 0;
+    if ((role == ap_xsd::Role::sink && flagsForMixPort) ||
+        (role == ap_xsd::Role::source && !flagsForMixPort)) {
+        for (const ap_xsd::AudioInOutFlag& flag : flags) {
+            audio_input_flags_t legacyFlag;
+            if (::android::InputFlagConverter::fromString(ap_xsd::toString(flag), legacyFlag)) {
+                flagMask |= static_cast<int>(legacyFlag);
+            }
+        }
+        return AudioIoFlags::make<AudioIoFlags::Tag::input>(flagMask);
+    } else {
+        for (const ap_xsd::AudioInOutFlag& flag : flags) {
+            audio_output_flags_t legacyFlag;
+            if (::android::OutputFlagConverter::fromString(ap_xsd::toString(flag), legacyFlag)) {
+                flagMask |= static_cast<int>(legacyFlag);
+            }
+        }
+        return AudioIoFlags::make<AudioIoFlags::Tag::output>(flagMask);
+    }
+}
+
+ConversionResult<AudioPort> convertDevicePortToAidl(
+        const ap_xsd::DevicePorts::DevicePort& xDevicePort, const std::string& xDefaultOutputDevice,
+        int32_t& nextPortId) {
+    return AudioPort{
+            .id = nextPortId++,
+            .name = NON_EMPTY_STRING_OR_FATAL(xDevicePort.getTagName()),
+            .profiles = VALUE_OR_FATAL((convertCollectionToAidl<ap_xsd::Profile, AudioProfile>(
+                    xDevicePort.getProfile(), convertAudioProfileToAidl))),
+            .flags = VALUE_OR_FATAL(convertIoFlagsToAidl({}, xDevicePort.getRole(), false)),
+            .gains = VALUE_OR_FATAL(
+                    (convertWrappedCollectionToAidl<ap_xsd::Gains, ap_xsd::Gains::Gain, AudioGain>(
+                            xDevicePort.getGains(), &ap_xsd::Gains::getGain, convertGainToAidl))),
+
+            .ext = VALUE_OR_FATAL(createAudioPortExt(xDevicePort, xDefaultOutputDevice))};
+}
+
+ConversionResult<std::vector<AudioPort>> convertDevicePortsInModuleToAidl(
+        const ap_xsd::Modules::Module& xModuleConfig, int32_t& nextPortId) {
+    std::vector<AudioPort> audioPortVec;
+    std::vector<ap_xsd::DevicePorts> xDevicePortsVec = xModuleConfig.getDevicePorts();
+    if (xDevicePortsVec.size() > 1) {
+        LOG(ERROR) << __func__ << "Having multiple '<devicePorts>' elements is not allowed, found: "
+                   << xDevicePortsVec.size();
+        return unexpected(BAD_VALUE);
+    }
+    if (!xDevicePortsVec.empty()) {
+        const std::string xDefaultOutputDevice = xModuleConfig.hasDefaultOutputDevice()
+                                                         ? xModuleConfig.getDefaultOutputDevice()
+                                                         : "";
+        audioPortVec.reserve(xDevicePortsVec[0].getDevicePort().size());
+        for (const ap_xsd::DevicePorts& xDevicePortsType : xDevicePortsVec) {
+            for (const ap_xsd::DevicePorts::DevicePort& xDevicePort :
+                 xDevicePortsType.getDevicePort()) {
+                audioPortVec.push_back(VALUE_OR_FATAL(
+                        convertDevicePortToAidl(xDevicePort, xDefaultOutputDevice, nextPortId)));
+            }
+        }
+    }
+    const std::unordered_set<std::string> xAttachedDeviceSet = getAttachedDevices(xModuleConfig);
+    for (const auto& port : audioPortVec) {
+        const auto& devicePort = port.ext.get<AudioPortExt::device>();
+        if (xAttachedDeviceSet.count(port.name) != devicePort.device.type.connection.empty()) {
+            LOG(ERROR) << __func__ << ": Review Audio Policy config: <attachedDevices> "
+                       << "list is incorrect or devicePort \"" << port.name
+                       << "\" type= " << devicePort.device.type.toString() << " is incorrect.";
+            return unexpected(BAD_VALUE);
+        }
+    }
+    return audioPortVec;
+}
+
+ConversionResult<AudioPort> convertMixPortToAidl(const ap_xsd::MixPorts::MixPort& xMixPort,
+                                                 int32_t& nextPortId) {
+    return AudioPort{
+            .id = nextPortId++,
+            .name = NON_EMPTY_STRING_OR_FATAL(xMixPort.getName()),
+            .profiles = VALUE_OR_FATAL((convertCollectionToAidl<ap_xsd::Profile, AudioProfile>(
+                    xMixPort.getProfile(), convertAudioProfileToAidl))),
+            .flags = xMixPort.hasFlags()
+                             ? VALUE_OR_FATAL(convertIoFlagsToAidl(xMixPort.getFlags(),
+                                                                   xMixPort.getRole(), true))
+                             : VALUE_OR_FATAL(convertIoFlagsToAidl({}, xMixPort.getRole(), true)),
+            .gains = VALUE_OR_FATAL(
+                    (convertWrappedCollectionToAidl<ap_xsd::Gains, ap_xsd::Gains::Gain, AudioGain>(
+                            xMixPort.getGains(), &ap_xsd::Gains::getGain, &convertGainToAidl))),
+            .ext = VALUE_OR_FATAL(createAudioPortExt(xMixPort)),
+    };
+}
+
+ConversionResult<std::vector<AudioPort>> convertMixPortsInModuleToAidl(
+        const ap_xsd::Modules::Module& xModuleConfig, int32_t& nextPortId) {
+    std::vector<AudioPort> audioPortVec;
+    std::vector<ap_xsd::MixPorts> xMixPortsVec = xModuleConfig.getMixPorts();
+    if (xMixPortsVec.size() > 1) {
+        LOG(ERROR) << __func__ << "Having multiple '<mixPorts>' elements is not allowed, found: "
+                   << xMixPortsVec.size();
+        return unexpected(BAD_VALUE);
+    }
+    if (!xMixPortsVec.empty()) {
+        audioPortVec.reserve(xMixPortsVec[0].getMixPort().size());
+        for (const ap_xsd::MixPorts& xMixPortsType : xMixPortsVec) {
+            for (const ap_xsd::MixPorts::MixPort& xMixPort : xMixPortsType.getMixPort()) {
+                audioPortVec.push_back(VALUE_OR_FATAL(convertMixPortToAidl(xMixPort, nextPortId)));
+            }
+        }
+    }
+    return audioPortVec;
+}
+
+ConversionResult<int32_t> getSinkPortId(const ap_xsd::Routes::Route& xRoute,
+                                        const std::unordered_map<std::string, int32_t>& portMap) {
+    auto portMapIter = portMap.find(xRoute.getSink());
+    if (portMapIter == portMap.end()) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config: audio route"
+                   << "has sink: " << xRoute.getSink()
+                   << " which is neither a device port nor mix port.";
+        return unexpected(BAD_VALUE);
+    }
+    return portMapIter->second;
+}
+
+ConversionResult<std::vector<int32_t>> getSourcePortIds(
+        const ap_xsd::Routes::Route& xRoute,
+        const std::unordered_map<std::string, int32_t>& portMap) {
+    std::vector<int32_t> sourcePortIds;
+    for (const std::string& rawSource : ::android::base::Split(xRoute.getSources(), ",")) {
+        const std::string source = ::android::base::Trim(rawSource);
+        auto portMapIter = portMap.find(source);
+        if (portMapIter == portMap.end()) {
+            LOG(ERROR) << __func__ << " Review Audio Policy config: audio route"
+                       << "has source \"" << source
+                       << "\" which is neither a device port nor mix port.";
+            return unexpected(BAD_VALUE);
+        }
+        sourcePortIds.push_back(portMapIter->second);
+    }
+    return sourcePortIds;
+}
+
+ConversionResult<AudioRoute> convertRouteToAidl(const ap_xsd::Routes::Route& xRoute,
+                                                const std::vector<AudioPort>& aidlAudioPorts) {
+    std::unordered_map<std::string, int32_t> portMap;
+    for (const AudioPort& port : aidlAudioPorts) {
+        portMap.insert({port.name, port.id});
+    }
+    return AudioRoute{.sourcePortIds = VALUE_OR_FATAL(getSourcePortIds(xRoute, portMap)),
+                      .sinkPortId = VALUE_OR_FATAL(getSinkPortId(xRoute, portMap)),
+                      .isExclusive = (xRoute.getType() == ap_xsd::MixType::mux)};
+}
+
+ConversionResult<std::vector<AudioRoute>> convertRoutesInModuleToAidl(
+        const ap_xsd::Modules::Module& xModuleConfig,
+        const std::vector<AudioPort>& aidlAudioPorts) {
+    std::vector<AudioRoute> audioRouteVec;
+    std::vector<ap_xsd::Routes> xRoutesVec = xModuleConfig.getRoutes();
+    if (!xRoutesVec.empty()) {
+        /*
+         * xRoutesVec likely only contains one element; that is, it's
+         * likely that all ap_xsd::Routes::MixPort types that we need to convert
+         * are inside of xRoutesVec[0].
+         */
+        audioRouteVec.reserve(xRoutesVec[0].getRoute().size());
+        for (const ap_xsd::Routes& xRoutesType : xRoutesVec) {
+            for (const ap_xsd::Routes::Route& xRoute : xRoutesType.getRoute()) {
+                audioRouteVec.push_back(VALUE_OR_FATAL(convertRouteToAidl(xRoute, aidlAudioPorts)));
+            }
+        }
+    }
+    return audioRouteVec;
+}
+
+ConversionResult<std::unique_ptr<Module::Configuration>> convertModuleConfigToAidl(
+        const ap_xsd::Modules::Module& xModuleConfig) {
+    auto result = std::make_unique<Module::Configuration>();
+    auto& aidlModuleConfig = *result;
+    std::vector<AudioPort> devicePorts = VALUE_OR_FATAL(
+            convertDevicePortsInModuleToAidl(xModuleConfig, aidlModuleConfig.nextPortId));
+
+    // The XML config does not specify the default input device.
+    // Assign the first attached input device as the default.
+    for (auto& port : devicePorts) {
+        if (port.flags.getTag() != AudioIoFlags::input) continue;
+        auto& deviceExt = port.ext.get<AudioPortExt::device>();
+        if (!deviceExt.device.type.connection.empty()) continue;
+        deviceExt.flags |= 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
+        break;
+    }
+
+    std::vector<AudioPort> mixPorts = VALUE_OR_FATAL(
+            convertMixPortsInModuleToAidl(xModuleConfig, aidlModuleConfig.nextPortId));
+    aidlModuleConfig.ports.reserve(devicePorts.size() + mixPorts.size());
+    aidlModuleConfig.ports.insert(aidlModuleConfig.ports.end(), devicePorts.begin(),
+                                  devicePorts.end());
+    aidlModuleConfig.ports.insert(aidlModuleConfig.ports.end(), mixPorts.begin(), mixPorts.end());
+
+    aidlModuleConfig.routes =
+            VALUE_OR_FATAL(convertRoutesInModuleToAidl(xModuleConfig, aidlModuleConfig.ports));
+    return result;
+}
+
+ConversionResult<AudioHalCapCriterion> convertCapCriterionToAidl(
+        const eng_xsd::CriterionType& xsdcCriterion) {
+    AudioHalCapCriterion aidlCapCriterion;
+    aidlCapCriterion.name = xsdcCriterion.getName();
+    aidlCapCriterion.criterionTypeName = xsdcCriterion.getType();
+    aidlCapCriterion.defaultLiteralValue = xsdcCriterion.get_default();
+    return aidlCapCriterion;
+}
+
+ConversionResult<std::string> convertCriterionTypeValueToAidl(
+        const eng_xsd::ValueType& xsdcCriterionTypeValue) {
+    return xsdcCriterionTypeValue.getLiteral();
+}
+
+ConversionResult<AudioHalCapCriterionType> convertCapCriterionTypeToAidl(
+        const eng_xsd::CriterionTypeType& xsdcCriterionType) {
+    AudioHalCapCriterionType aidlCapCriterionType;
+    aidlCapCriterionType.name = xsdcCriterionType.getName();
+    aidlCapCriterionType.isInclusive = !(static_cast<bool>(xsdcCriterionType.getType()));
+    aidlCapCriterionType.values = VALUE_OR_RETURN(
+            (convertWrappedCollectionToAidl<eng_xsd::ValuesType, eng_xsd::ValueType, std::string>(
+                    xsdcCriterionType.getValues(), &eng_xsd::ValuesType::getValue,
+                    &convertCriterionTypeValueToAidl)));
+    return aidlCapCriterionType;
+}
+
+ConversionResult<AudioHalVolumeCurve::CurvePoint> convertCurvePointToAidl(
+        const std::string& xsdcCurvePoint) {
+    AudioHalVolumeCurve::CurvePoint aidlCurvePoint{};
+    if ((sscanf(xsdcCurvePoint.c_str(), "%" SCNd8 ",%d", &aidlCurvePoint.index,
+                &aidlCurvePoint.attenuationMb) != 2) ||
+        (aidlCurvePoint.index < AudioHalVolumeCurve::CurvePoint::MIN_INDEX) ||
+        (aidlCurvePoint.index > AudioHalVolumeCurve::CurvePoint::MAX_INDEX)) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config: volume curve point:"
+                   << "\"" << xsdcCurvePoint << "\" is invalid";
+        return unexpected(BAD_VALUE);
+    }
+    return aidlCurvePoint;
+}
+}  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp
index 63a014a..8727232 100644
--- a/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp
+++ b/audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp
@@ -74,7 +74,7 @@
         .common = {.id = {.type = getEffectTypeUuidAcousticEchoCanceler(),
                           .uuid = getEffectImplUuidAcousticEchoCancelerSw(),
                           .proxy = std::nullopt},
-                   .flags = {.type = Flags::Type::INSERT,
+                   .flags = {.type = Flags::Type::PRE_PROC,
                              .insert = Flags::Insert::FIRST,
                              .volume = Flags::Volume::CTRL},
                    .name = AcousticEchoCancelerSw::kEffectName,
diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.xml b/audio/aidl/default/android.hardware.audio.service-aidl.xml
index 9db6061..57f61c9 100644
--- a/audio/aidl/default/android.hardware.audio.service-aidl.xml
+++ b/audio/aidl/default/android.hardware.audio.service-aidl.xml
@@ -12,16 +12,6 @@
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
     <version>1</version>
-    <fqname>IModule/stub</fqname>
-  </hal>
-  <hal format="aidl">
-    <name>android.hardware.audio.core</name>
-    <version>1</version>
-    <fqname>IModule/usb</fqname>
-  </hal>
-  <hal format="aidl">
-    <name>android.hardware.audio.core</name>
-    <version>1</version>
     <fqname>IModule/bluetooth</fqname>
   </hal>
   <hal format="aidl">
@@ -29,4 +19,16 @@
     <version>1</version>
     <fqname>IConfig/default</fqname>
   </hal>
+  <!-- Uncomment when these modules present in the configuration
+  <hal format="aidl">
+    <name>android.hardware.audio.core</name>
+    <version>1</version>
+    <fqname>IModule/stub</fqname>
+  </hal>
+  <hal format="aidl">
+    <name>android.hardware.audio.core</name>
+    <version>1</version>
+    <fqname>IModule/usb</fqname>
+  </hal>
+  -->
 </manifest>
diff --git a/audio/aidl/default/bluetooth/ModuleBluetooth.cpp b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
index bfe7ca0..3c33207 100644
--- a/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
+++ b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
@@ -18,15 +18,23 @@
 
 #include <android-base/logging.h>
 
+#include "BluetoothAudioSessionControl.h"
 #include "core-impl/ModuleBluetooth.h"
 #include "core-impl/StreamBluetooth.h"
 
 namespace aidl::android::hardware::audio::core {
 
-using aidl::android::hardware::audio::common::SinkMetadata;
-using aidl::android::hardware::audio::common::SourceMetadata;
-using aidl::android::media::audio::common::AudioOffloadInfo;
-using aidl::android::media::audio::common::MicrophoneInfo;
+using ::aidl::android::hardware::audio::common::SinkMetadata;
+using ::aidl::android::hardware::audio::common::SourceMetadata;
+using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+using ::aidl::android::media::audio::common::AudioDeviceType;
+using ::aidl::android::media::audio::common::AudioOffloadInfo;
+using ::aidl::android::media::audio::common::AudioPort;
+using ::aidl::android::media::audio::common::AudioPortExt;
+using ::aidl::android::media::audio::common::MicrophoneInfo;
+using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidl;
+using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut;
 
 ndk::ScopedAStatus ModuleBluetooth::getBluetoothA2dp(
         std::shared_ptr<IBluetoothA2dp>* _aidl_return) {
@@ -80,6 +88,49 @@
                                                     offloadInfo, getBtProfileManagerHandles());
 }
 
+ndk::ScopedAStatus ModuleBluetooth::populateConnectedDevicePort(AudioPort* audioPort) {
+    if (audioPort->ext.getTag() != AudioPortExt::device) {
+        LOG(ERROR) << __func__ << ": not a device port: " << audioPort->toString();
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    const auto& devicePort = audioPort->ext.get<AudioPortExt::device>();
+    const auto& description = devicePort.device.type;
+    // Since the configuration of the BT module is static, there is nothing to populate here.
+    // However, this method must return an error when the device can not be connected,
+    // this is determined by the status of BT profiles.
+    if (description.connection == AudioDeviceDescription::CONNECTION_BT_A2DP) {
+        bool isA2dpEnabled = false;
+        if (!!mBluetoothA2dp) {
+            RETURN_STATUS_IF_ERROR(mBluetoothA2dp.getInstance()->isEnabled(&isA2dpEnabled));
+        }
+        return isA2dpEnabled ? ndk::ScopedAStatus::ok()
+                             : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE) {
+        bool isLeEnabled = false;
+        if (!!mBluetoothLe) {
+            RETURN_STATUS_IF_ERROR(mBluetoothLe.getInstance()->isEnabled(&isLeEnabled));
+        }
+        return isLeEnabled ? ndk::ScopedAStatus::ok()
+                           : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    } else if (description.connection == AudioDeviceDescription::CONNECTION_WIRELESS &&
+               description.type == AudioDeviceType::OUT_HEARING_AID) {
+        // Hearing aids can use a number of profiles, thus the only way to check
+        // connectivity is to try to talk to the BT HAL.
+        if (!BluetoothAudioSession::IsAidlAvailable()) {
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        }
+        std::shared_ptr<BluetoothAudioPortAidl> proxy = std::shared_ptr<BluetoothAudioPortAidl>(
+                std::make_shared<BluetoothAudioPortAidlOut>());
+        if (proxy->registerPort(description)) {
+            proxy->unregisterPort();
+            return ndk::ScopedAStatus::ok();
+        }
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    LOG(ERROR) << __func__ << ": unsupported device type: " << audioPort->toString();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
 ndk::ScopedAStatus ModuleBluetooth::onMasterMuteChanged(bool) {
     LOG(DEBUG) << __func__ << ": is not supported";
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt
index e2bc833..3547f54 100644
--- a/audio/aidl/default/config/audioPolicy/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/api/current.txt
@@ -85,16 +85,6 @@
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_TRI_BACK;
   }
 
-  public enum AudioContentType {
-    method @NonNull public String getRawName();
-    enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_MOVIE;
-    enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_MUSIC;
-    enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_SONIFICATION;
-    enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_SPEECH;
-    enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_ULTRASOUND;
-    enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_UNKNOWN;
-  }
-
   public enum AudioDevice {
     method @NonNull public String getRawName();
     enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_AMBIENT;
@@ -168,13 +158,6 @@
     enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADSET;
   }
 
-  public enum AudioEncapsulationType {
-    method @NonNull public String getRawName();
-    enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_IEC61937;
-    enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_NONE;
-    enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_PCM;
-  }
-
   public enum AudioFormat {
     method @NonNull public String getRawName();
     enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC;
@@ -359,29 +342,6 @@
     enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_VOICE_CALL;
   }
 
-  public enum AudioUsage {
-    method @NonNull public String getRawName();
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ALARM;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ANNOUNCEMENT;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ASSISTANCE_SONIFICATION;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ASSISTANT;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_CALL_ASSISTANT;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_EMERGENCY;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_GAME;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_MEDIA;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_NOTIFICATION;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_NOTIFICATION_EVENT;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_SAFETY;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_UNKNOWN;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_VEHICLE_STATUS;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_VIRTUAL_SOURCE;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION;
-    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
-  }
-
   public enum DeviceCategory {
     method @NonNull public String getRawName();
     enum_constant public static final android.audio.policy.configuration.DeviceCategory DEVICE_CATEGORY_EARPIECE;
@@ -435,7 +395,6 @@
     method @Nullable public int getMinRampMs();
     method @Nullable public int getMinValueMB();
     method @Nullable public java.util.List<android.audio.policy.configuration.AudioGainMode> getMode();
-    method @Nullable public String getName();
     method @Nullable public int getStepValueMB();
     method @Nullable public boolean getUseForVolume();
     method public void setChannel_mask(@Nullable android.audio.policy.configuration.AudioChannelMask);
@@ -445,7 +404,6 @@
     method public void setMinRampMs(@Nullable int);
     method public void setMinValueMB(@Nullable int);
     method public void setMode(@Nullable java.util.List<android.audio.policy.configuration.AudioGainMode>);
-    method public void setName(@Nullable String);
     method public void setStepValueMB(@Nullable int);
     method public void setUseForVolume(@Nullable boolean);
   }
@@ -478,7 +436,6 @@
     method @Nullable public long getMaxActiveCount();
     method @Nullable public long getMaxOpenCount();
     method @Nullable public String getName();
-    method @Nullable public java.util.List<android.audio.policy.configuration.AudioUsage> getPreferredUsage();
     method @Nullable public java.util.List<android.audio.policy.configuration.Profile> getProfile();
     method @Nullable public long getRecommendedMuteDurationMs();
     method @Nullable public android.audio.policy.configuration.Role getRole();
@@ -487,7 +444,6 @@
     method public void setMaxActiveCount(@Nullable long);
     method public void setMaxOpenCount(@Nullable long);
     method public void setName(@Nullable String);
-    method public void setPreferredUsage(@Nullable java.util.List<android.audio.policy.configuration.AudioUsage>);
     method public void setRecommendedMuteDurationMs(@Nullable long);
     method public void setRole(@Nullable android.audio.policy.configuration.Role);
   }
@@ -524,14 +480,10 @@
   public class Profile {
     ctor public Profile();
     method @Nullable public java.util.List<android.audio.policy.configuration.AudioChannelMask> getChannelMasks();
-    method @Nullable public android.audio.policy.configuration.AudioEncapsulationType getEncapsulationType();
     method @Nullable public String getFormat();
-    method @Nullable public String getName();
     method @Nullable public java.util.List<java.math.BigInteger> getSamplingRates();
     method public void setChannelMasks(@Nullable java.util.List<android.audio.policy.configuration.AudioChannelMask>);
-    method public void setEncapsulationType(@Nullable android.audio.policy.configuration.AudioEncapsulationType);
     method public void setFormat(@Nullable String);
-    method public void setName(@Nullable String);
     method public void setSamplingRates(@Nullable java.util.List<java.math.BigInteger>);
   }
 
diff --git a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
index 9a3a447..d93f697 100644
--- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
@@ -217,20 +217,6 @@
                     <xs:attribute name="flags" type="audioInOutFlags"/>
                     <xs:attribute name="maxOpenCount" type="xs:unsignedInt"/>
                     <xs:attribute name="maxActiveCount" type="xs:unsignedInt"/>
-                    <xs:attribute name="preferredUsage" type="audioUsageList">
-                        <xs:annotation>
-                            <xs:documentation xml:lang="en">
-                                When choosing the mixPort of an audio track, the audioPolicy
-                                first considers the mixPorts with a preferredUsage including
-                                the track AudioUsage preferred .
-                                If non support the track format, the other mixPorts are considered.
-                                Eg: a <mixPort preferredUsage="AUDIO_USAGE_MEDIA" /> will receive
-                                    the audio of all apps playing with a MEDIA usage.
-                                    It may receive audio from ALARM if there are no audio compatible
-                                    <mixPort preferredUsage="AUDIO_USAGE_ALARM" />.
-                             </xs:documentation>
-                        </xs:annotation>
-                    </xs:attribute>
                     <xs:attribute name="recommendedMuteDurationMs" type="xs:unsignedInt"/>
                 </xs:complexType>
                 <xs:unique name="mixPortProfileUniqueness">
@@ -434,56 +420,6 @@
     <xs:simpleType name="extendableAudioFormat">
         <xs:union memberTypes="audioFormat vendorExtension"/>
     </xs:simpleType>
-    <xs:simpleType name="audioUsage">
-        <xs:annotation>
-            <xs:documentation xml:lang="en">
-                Audio usage specifies the intended use case for the sound being played.
-                Please consult frameworks/base/media/java/android/media/AudioAttributes.java
-                for the description of each value.
-            </xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:enumeration value="AUDIO_USAGE_UNKNOWN" />
-            <xs:enumeration value="AUDIO_USAGE_MEDIA" />
-            <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION" />
-            <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
-            <xs:enumeration value="AUDIO_USAGE_ALARM" />
-            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION" />
-            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
-            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_EVENT" />
-            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
-            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
-            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
-            <xs:enumeration value="AUDIO_USAGE_GAME" />
-            <xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE" />
-            <xs:enumeration value="AUDIO_USAGE_ASSISTANT" />
-            <xs:enumeration value="AUDIO_USAGE_CALL_ASSISTANT" />
-            <xs:enumeration value="AUDIO_USAGE_EMERGENCY" />
-            <xs:enumeration value="AUDIO_USAGE_SAFETY" />
-            <xs:enumeration value="AUDIO_USAGE_VEHICLE_STATUS" />
-            <xs:enumeration value="AUDIO_USAGE_ANNOUNCEMENT" />
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="audioUsageList">
-        <xs:list itemType="audioUsage"/>
-    </xs:simpleType>
-    <xs:simpleType name="audioContentType">
-        <xs:annotation>
-            <xs:documentation xml:lang="en">
-                Audio content type expresses the general category of the content.
-                Please consult frameworks/base/media/java/android/media/AudioAttributes.java
-                for the description of each value.
-            </xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:enumeration value="AUDIO_CONTENT_TYPE_UNKNOWN"/>
-            <xs:enumeration value="AUDIO_CONTENT_TYPE_SPEECH"/>
-            <xs:enumeration value="AUDIO_CONTENT_TYPE_MUSIC"/>
-            <xs:enumeration value="AUDIO_CONTENT_TYPE_MOVIE"/>
-            <xs:enumeration value="AUDIO_CONTENT_TYPE_SONIFICATION"/>
-            <xs:enumeration value="AUDIO_CONTENT_TYPE_ULTRASOUND"/>
-        </xs:restriction>
-    </xs:simpleType>
     <xs:simpleType name="samplingRates">
         <xs:list itemType="xs:nonNegativeInteger" />
     </xs:simpleType>
@@ -579,19 +515,10 @@
     <xs:simpleType name="channelMasks">
         <xs:list itemType="audioChannelMask" />
     </xs:simpleType>
-    <xs:simpleType name="audioEncapsulationType">
-        <xs:restriction base="xs:string">
-            <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_NONE"/>
-            <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_IEC61937"/>
-            <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_PCM"/>
-        </xs:restriction>
-    </xs:simpleType>
     <xs:complexType name="profile">
-        <xs:attribute name="name" type="xs:token" use="optional"/>
         <xs:attribute name="format" type="extendableAudioFormat" use="optional"/>
         <xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
         <xs:attribute name="channelMasks" type="channelMasks" use="optional"/>
-        <xs:attribute name="encapsulationType" type="audioEncapsulationType" use="optional"/>
     </xs:complexType>
     <xs:simpleType name="audioGainMode">
         <xs:restriction base="xs:string">
@@ -612,7 +539,6 @@
         <xs:sequence>
             <xs:element name="gain" minOccurs="0" maxOccurs="unbounded">
                 <xs:complexType>
-                    <xs:attribute name="name" type="xs:token" use="required"/>
                     <xs:attribute name="mode" type="audioGainModeMask" use="required"/>
                     <xs:attribute name="channel_mask" type="audioChannelMask" use="optional"/>
                     <xs:attribute name="minValueMB" type="xs:int" use="optional"/>
diff --git a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
index ed6cfa0..e8f90b2 100644
--- a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
+++ b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
@@ -93,7 +93,7 @@
         .common = {.id = {.type = getEffectTypeUuidDynamicsProcessing(),
                           .uuid = getEffectImplUuidDynamicsProcessingSw(),
                           .proxy = std::nullopt},
-                   .flags = {.type = Flags::Type::INSERT,
+                   .flags = {.type = Flags::Type::POST_PROC,
                              .insert = Flags::Insert::FIRST,
                              .volume = Flags::Volume::CTRL},
                    .name = DynamicsProcessingSw::kEffectName,
diff --git a/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h b/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h
index 090d585..bff4b4a 100644
--- a/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h
+++ b/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h
@@ -16,27 +16,42 @@
 
 #pragma once
 
+#include <memory>
+#include <optional>
 #include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
 
 #include <aidl/android/hardware/audio/core/SurroundSoundConfig.h>
 #include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
 #include <android_audio_policy_configuration.h>
 #include <android_audio_policy_configuration_enums.h>
+#include <media/AidlConversionUtil.h>
 
+#include "core-impl/Module.h"
 #include "core-impl/XmlConverter.h"
 
 namespace aidl::android::hardware::audio::core::internal {
 
 class AudioPolicyConfigXmlConverter {
   public:
+    using ModuleConfiguration = std::pair<std::string, std::unique_ptr<Module::Configuration>>;
+    using ModuleConfigs = std::vector<ModuleConfiguration>;
+
     explicit AudioPolicyConfigXmlConverter(const std::string& configFilePath)
-        : mConverter(configFilePath, &::android::audio::policy::configuration::read) {}
+        : mConverter(configFilePath, &::android::audio::policy::configuration::read) {
+        if (mConverter.getXsdcConfig()) {
+            init();
+        }
+    }
 
     std::string getError() const { return mConverter.getError(); }
     ::android::status_t getStatus() const { return mConverter.getStatus(); }
 
     const ::aidl::android::media::audio::common::AudioHalEngineConfig& getAidlEngineConfig();
     const SurroundSoundConfig& getSurroundSoundConfig();
+    std::unique_ptr<ModuleConfigs> releaseModuleConfigs();
 
     // Public for testing purposes.
     static const SurroundSoundConfig& getDefaultSurroundSoundConfig();
@@ -47,13 +62,13 @@
         return mConverter.getXsdcConfig();
     }
     void addVolumeGroupstoEngineConfig();
+    void init();
     void mapStreamToVolumeCurve(
             const ::android::audio::policy::configuration::Volume& xsdcVolumeCurve);
     void mapStreamsToVolumeCurves();
     void parseVolumes();
-    ::aidl::android::media::audio::common::AudioHalVolumeCurve::CurvePoint convertCurvePointToAidl(
-            const std::string& xsdcCurvePoint);
-    ::aidl::android::media::audio::common::AudioHalVolumeCurve convertVolumeCurveToAidl(
+    ConversionResult<::aidl::android::media::audio::common::AudioHalVolumeCurve>
+    convertVolumeCurveToAidl(
             const ::android::audio::policy::configuration::Volume& xsdcVolumeCurve);
 
     ::aidl::android::media::audio::common::AudioHalEngineConfig mAidlEngineConfig;
@@ -63,6 +78,7 @@
     std::unordered_map<::android::audio::policy::configuration::AudioStreamType,
                        std::vector<::aidl::android::media::audio::common::AudioHalVolumeCurve>>
             mStreamToVolumeCurvesMap;
+    std::unique_ptr<ModuleConfigs> mModuleConfigurations = std::make_unique<ModuleConfigs>();
 };
 
 }  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/include/core-impl/ChildInterface.h b/audio/aidl/default/include/core-impl/ChildInterface.h
index 2421b59..3b74c5e 100644
--- a/audio/aidl/default/include/core-impl/ChildInterface.h
+++ b/audio/aidl/default/include/core-impl/ChildInterface.h
@@ -42,12 +42,16 @@
     C* operator->() const { return this->first; }
     // Use 'getInstance' when returning the interface instance.
     std::shared_ptr<C> getInstance() {
+        (void)getBinder();
+        return this->first;
+    }
+    AIBinder* getBinder() {
         if (this->second.get() == nullptr) {
             this->second = this->first->asBinder();
             AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL,
                                            ANDROID_PRIORITY_AUDIO);
         }
-        return this->first;
+        return this->second.get();
     }
 };
 
diff --git a/audio/aidl/default/include/core-impl/Config.h b/audio/aidl/default/include/core-impl/Config.h
index 96a6cb9..63d4b3d 100644
--- a/audio/aidl/default/include/core-impl/Config.h
+++ b/audio/aidl/default/include/core-impl/Config.h
@@ -26,11 +26,16 @@
 static const std::string kEngineConfigFileName = "audio_policy_engine_configuration.xml";
 
 class Config : public BnConfig {
+  public:
+    explicit Config(internal::AudioPolicyConfigXmlConverter& apConverter)
+        : mAudioPolicyConverter(apConverter) {}
+
+  private:
     ndk::ScopedAStatus getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) override;
     ndk::ScopedAStatus getEngineConfig(
             aidl::android::media::audio::common::AudioHalEngineConfig* _aidl_return) override;
-    internal::AudioPolicyConfigXmlConverter mAudioPolicyConverter{
-            ::android::audio_get_audio_policy_config_file()};
+
+    internal::AudioPolicyConfigXmlConverter& mAudioPolicyConverter;
     internal::EngineConfigXmlConverter mEngConfigConverter{
             ::android::audio_find_readable_configuration_file(kEngineConfigFileName.c_str())};
 };
diff --git a/audio/aidl/default/include/core-impl/Configuration.h b/audio/aidl/default/include/core-impl/Configuration.h
index 6277c38..a56c8c9 100644
--- a/audio/aidl/default/include/core-impl/Configuration.h
+++ b/audio/aidl/default/include/core-impl/Configuration.h
@@ -16,37 +16,14 @@
 
 #pragma once
 
-#include <map>
 #include <memory>
-#include <vector>
 
-#include <aidl/android/hardware/audio/core/AudioPatch.h>
-#include <aidl/android/hardware/audio/core/AudioRoute.h>
-#include <aidl/android/media/audio/common/AudioPort.h>
-#include <aidl/android/media/audio/common/AudioPortConfig.h>
-#include <aidl/android/media/audio/common/MicrophoneInfo.h>
+#include "Module.h"
 
 namespace aidl::android::hardware::audio::core::internal {
 
-struct Configuration {
-    std::vector<::aidl::android::media::audio::common::MicrophoneInfo> microphones;
-    std::vector<::aidl::android::media::audio::common::AudioPort> ports;
-    std::vector<::aidl::android::media::audio::common::AudioPortConfig> portConfigs;
-    std::vector<::aidl::android::media::audio::common::AudioPortConfig> initialConfigs;
-    // Port id -> List of profiles to use when the device port state is set to 'connected'
-    // in connection simulation mode.
-    std::map<int32_t, std::vector<::aidl::android::media::audio::common::AudioProfile>>
-            connectedProfiles;
-    std::vector<AudioRoute> routes;
-    std::vector<AudioPatch> patches;
-    int32_t nextPortId = 1;
-    int32_t nextPatchId = 1;
-};
-
-std::unique_ptr<Configuration> getPrimaryConfiguration();
-std::unique_ptr<Configuration> getRSubmixConfiguration();
-std::unique_ptr<Configuration> getStubConfiguration();
-std::unique_ptr<Configuration> getUsbConfiguration();
-std::unique_ptr<Configuration> getBluetoothConfiguration();
+std::unique_ptr<Module::Configuration> getConfiguration(Module::Type moduleType);
+std::vector<aidl::android::media::audio::common::AudioProfile>
+getStandard16And24BitPcmAudioProfiles();
 
 }  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h b/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h
index b34441d..22ac8cb 100644
--- a/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h
+++ b/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h
@@ -19,10 +19,9 @@
 #include <string>
 #include <unordered_map>
 
-#include <utils/Errors.h>
-
 #include <android_audio_policy_engine_configuration.h>
 #include <android_audio_policy_engine_configuration_enums.h>
+#include <media/AidlConversionUtil.h>
 
 #include "core-impl/XmlConverter.h"
 
@@ -49,29 +48,24 @@
     }
     void init();
     void initProductStrategyMap();
-    ::aidl::android::media::audio::common::AudioAttributes convertAudioAttributesToAidl(
+    ConversionResult<::aidl::android::media::audio::common::AudioAttributes>
+    convertAudioAttributesToAidl(
             const ::android::audio::policy::engine::configuration::AttributesType&
                     xsdcAudioAttributes);
-    ::aidl::android::media::audio::common::AudioHalAttributesGroup convertAttributesGroupToAidl(
+    ConversionResult<::aidl::android::media::audio::common::AudioHalAttributesGroup>
+    convertAttributesGroupToAidl(
             const ::android::audio::policy::engine::configuration::AttributesGroup&
                     xsdcAttributesGroup);
-    ::aidl::android::media::audio::common::AudioHalCapCriterion convertCapCriterionToAidl(
-            const ::android::audio::policy::engine::configuration::CriterionType& xsdcCriterion);
-    ::aidl::android::media::audio::common::AudioHalCapCriterionType convertCapCriterionTypeToAidl(
-            const ::android::audio::policy::engine::configuration::CriterionTypeType&
-                    xsdcCriterionType);
-    std::string convertCriterionTypeValueToAidl(
-            const ::android::audio::policy::engine::configuration::ValueType&
-                    xsdcCriterionTypeValue);
-    ::aidl::android::media::audio::common::AudioHalVolumeCurve::CurvePoint convertCurvePointToAidl(
-            const std::string& xsdcCurvePoint);
-    ::aidl::android::media::audio::common::AudioHalProductStrategy convertProductStrategyToAidl(
-            const ::android::audio::policy::engine::configuration::ProductStrategies::
-                    ProductStrategy& xsdcProductStrategy);
-    int convertProductStrategyNameToAidl(const std::string& xsdcProductStrategyName);
-    ::aidl::android::media::audio::common::AudioHalVolumeCurve convertVolumeCurveToAidl(
+    ConversionResult<::aidl::android::media::audio::common::AudioHalProductStrategy>
+    convertProductStrategyToAidl(const ::android::audio::policy::engine::configuration::
+                                         ProductStrategies::ProductStrategy& xsdcProductStrategy);
+    ConversionResult<int> convertProductStrategyNameToAidl(
+            const std::string& xsdcProductStrategyName);
+    ConversionResult<::aidl::android::media::audio::common::AudioHalVolumeCurve>
+    convertVolumeCurveToAidl(
             const ::android::audio::policy::engine::configuration::Volume& xsdcVolumeCurve);
-    ::aidl::android::media::audio::common::AudioHalVolumeGroup convertVolumeGroupToAidl(
+    ConversionResult<::aidl::android::media::audio::common::AudioHalVolumeGroup>
+    convertVolumeGroupToAidl(
             const ::android::audio::policy::engine::configuration::VolumeGroupsType::VolumeGroup&
                     xsdcVolumeGroup);
 
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index bfdab51..718c07d 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -19,31 +19,49 @@
 #include <iostream>
 #include <map>
 #include <memory>
+#include <optional>
 #include <set>
 
 #include <aidl/android/hardware/audio/core/BnModule.h>
 
 #include "core-impl/ChildInterface.h"
-#include "core-impl/Configuration.h"
 #include "core-impl/Stream.h"
 
 namespace aidl::android::hardware::audio::core {
 
 class Module : public BnModule {
   public:
-    // This value is used for all AudioPatches and reported by all streams.
-    static constexpr int32_t kLatencyMs = 10;
+    struct Configuration {
+        std::vector<::aidl::android::media::audio::common::AudioPort> ports;
+        std::vector<::aidl::android::media::audio::common::AudioPortConfig> portConfigs;
+        std::vector<::aidl::android::media::audio::common::AudioPortConfig> initialConfigs;
+        // Port id -> List of profiles to use when the device port state is set to 'connected'
+        // in connection simulation mode.
+        std::map<int32_t, std::vector<::aidl::android::media::audio::common::AudioProfile>>
+                connectedProfiles;
+        std::vector<AudioRoute> routes;
+        std::vector<AudioPatch> patches;
+        int32_t nextPortId = 1;
+        int32_t nextPatchId = 1;
+    };
     enum Type : int { DEFAULT, R_SUBMIX, STUB, USB, BLUETOOTH };
     enum BtInterface : int { BTCONF, BTA2DP, BTLE };
-
-    static std::shared_ptr<Module> createInstance(Type type);
-
-    explicit Module(Type type) : mType(type) {}
-
     typedef std::tuple<std::weak_ptr<IBluetooth>, std::weak_ptr<IBluetoothA2dp>,
                        std::weak_ptr<IBluetoothLe>>
             BtProfileHandles;
 
+    // This value is used by default for all AudioPatches and reported by all streams.
+    static constexpr int32_t kLatencyMs = 10;
+
+    static std::shared_ptr<Module> createInstance(Type type) {
+        return createInstance(type, std::make_unique<Configuration>());
+    }
+    static std::shared_ptr<Module> createInstance(Type type,
+                                                  std::unique_ptr<Configuration>&& config);
+    static std::optional<Type> typeFromString(const std::string& type);
+
+    Module(Type type, std::unique_ptr<Configuration>&& config);
+
   protected:
     // The vendor extension done via inheritance can override interface methods and augment
     // a call to the base implementation.
@@ -148,7 +166,7 @@
     using Patches = std::multimap<int32_t, int32_t>;
 
     const Type mType;
-    std::unique_ptr<internal::Configuration> mConfig;
+    std::unique_ptr<Configuration> mConfig;
     ModuleDebug mDebug;
     VendorDebug mVendorDebug;
     ConnectedDevicePorts mConnectedDevicePorts;
@@ -187,7 +205,8 @@
             const ::aidl::android::media::audio::common::AudioPort& audioPort, bool connected);
     virtual ndk::ScopedAStatus onMasterMuteChanged(bool mute);
     virtual ndk::ScopedAStatus onMasterVolumeChanged(float volume);
-    virtual std::unique_ptr<internal::Configuration> initializeConfig();
+    virtual std::vector<::aidl::android::media::audio::common::MicrophoneInfo> getMicrophoneInfos();
+    virtual std::unique_ptr<Configuration> initializeConfig();
 
     // Utility and helper functions accessible to subclasses.
     ndk::ScopedAStatus bluetoothParametersUpdated();
@@ -202,16 +221,20 @@
     std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
     ndk::ScopedAStatus findPortIdForNewStream(
             int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
+    std::vector<AudioRoute*> getAudioRoutesForAudioPortImpl(int32_t portId);
     virtual BtProfileHandles getBtProfileManagerHandles();
-    internal::Configuration& getConfig();
+    Configuration& getConfig();
     const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
     bool getMasterMute() const { return mMasterMute; }
     bool getMasterVolume() const { return mMasterVolume; }
     bool getMicMute() const { return mMicMute; }
     const Patches& getPatches() const { return mPatches; }
+    std::set<int32_t> getRoutableAudioPortIds(int32_t portId,
+                                              std::vector<AudioRoute*>* routes = nullptr);
     const Streams& getStreams() const { return mStreams; }
     Type getType() const { return mType; }
     bool isMmapSupported();
+    void populateConnectedProfiles();
     template <typename C>
     std::set<int32_t> portIdsFromPortConfigIds(C portConfigIds);
     void registerPatch(const AudioPatch& patch);
diff --git a/audio/aidl/default/include/core-impl/ModuleAlsa.h b/audio/aidl/default/include/core-impl/ModuleAlsa.h
index 5815961..2774fe5 100644
--- a/audio/aidl/default/include/core-impl/ModuleAlsa.h
+++ b/audio/aidl/default/include/core-impl/ModuleAlsa.h
@@ -27,7 +27,8 @@
 // provide necessary overrides for all interface methods omitted here.
 class ModuleAlsa : public Module {
   public:
-    explicit ModuleAlsa(Module::Type type) : Module(type) {}
+    ModuleAlsa(Type type, std::unique_ptr<Configuration>&& config)
+        : Module(type, std::move(config)) {}
 
   protected:
     // Extension methods of 'Module'.
diff --git a/audio/aidl/default/include/core-impl/ModuleBluetooth.h b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
index 68b4e6b..7ac2d34 100644
--- a/audio/aidl/default/include/core-impl/ModuleBluetooth.h
+++ b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
@@ -23,7 +23,8 @@
 
 class ModuleBluetooth final : public Module {
   public:
-    ModuleBluetooth() : Module(Type::BLUETOOTH) {}
+    ModuleBluetooth(std::unique_ptr<Configuration>&& config)
+        : Module(Type::BLUETOOTH, std::move(config)) {}
 
   private:
     BtProfileHandles getBtProfileManagerHandles() override;
@@ -44,6 +45,8 @@
             const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
                     offloadInfo,
             std::shared_ptr<StreamOut>* result) override;
+    ndk::ScopedAStatus populateConnectedDevicePort(
+            ::aidl::android::media::audio::common::AudioPort* audioPort) override;
     ndk::ScopedAStatus onMasterMuteChanged(bool mute) override;
     ndk::ScopedAStatus onMasterVolumeChanged(float volume) override;
 
@@ -51,4 +54,4 @@
     ChildInterface<IBluetoothLe> mBluetoothLe;
 };
 
-}  // namespace aidl::android::hardware::audio::core
\ No newline at end of file
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/ModulePrimary.h b/audio/aidl/default/include/core-impl/ModulePrimary.h
index 6264237..ee86d64 100644
--- a/audio/aidl/default/include/core-impl/ModulePrimary.h
+++ b/audio/aidl/default/include/core-impl/ModulePrimary.h
@@ -22,7 +22,8 @@
 
 class ModulePrimary final : public Module {
   public:
-    ModulePrimary() : Module(Type::DEFAULT) {}
+    ModulePrimary(std::unique_ptr<Configuration>&& config)
+        : Module(Type::DEFAULT, std::move(config)) {}
 
   protected:
     ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
diff --git a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
index c4bf7b9..ebf4558 100644
--- a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
+++ b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
@@ -22,7 +22,8 @@
 
 class ModuleRemoteSubmix : public Module {
   public:
-    ModuleRemoteSubmix() : Module(Type::R_SUBMIX) {}
+    ModuleRemoteSubmix(std::unique_ptr<Configuration>&& config)
+        : Module(Type::R_SUBMIX, std::move(config)) {}
 
   private:
     // IModule interfaces
diff --git a/audio/aidl/default/include/core-impl/ModuleStub.h b/audio/aidl/default/include/core-impl/ModuleStub.h
index 4f77161..e9b7db4 100644
--- a/audio/aidl/default/include/core-impl/ModuleStub.h
+++ b/audio/aidl/default/include/core-impl/ModuleStub.h
@@ -22,7 +22,7 @@
 
 class ModuleStub final : public Module {
   public:
-    ModuleStub() : Module(Type::STUB) {}
+    ModuleStub(std::unique_ptr<Configuration>&& config) : Module(Type::STUB, std::move(config)) {}
 
   protected:
     ndk::ScopedAStatus getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) override;
diff --git a/audio/aidl/default/include/core-impl/ModuleUsb.h b/audio/aidl/default/include/core-impl/ModuleUsb.h
index a296b8c..6ee8f8a 100644
--- a/audio/aidl/default/include/core-impl/ModuleUsb.h
+++ b/audio/aidl/default/include/core-impl/ModuleUsb.h
@@ -22,7 +22,7 @@
 
 class ModuleUsb final : public ModuleAlsa {
   public:
-    ModuleUsb() : ModuleAlsa(Type::USB) {}
+    ModuleUsb(std::unique_ptr<Configuration>&& config) : ModuleAlsa(Type::USB, std::move(config)) {}
 
   private:
     // IModule interfaces
diff --git a/audio/aidl/default/include/core-impl/XmlConverter.h b/audio/aidl/default/include/core-impl/XmlConverter.h
index 383ea24..68e6b8e 100644
--- a/audio/aidl/default/include/core-impl/XmlConverter.h
+++ b/audio/aidl/default/include/core-impl/XmlConverter.h
@@ -22,7 +22,6 @@
 
 #include <media/AidlConversionUtil.h>
 #include <system/audio_config.h>
-#include <utils/Errors.h>
 
 namespace aidl::android::hardware::audio::core::internal {
 
@@ -85,10 +84,10 @@
  *     </Modules>
  */
 template <typename W, typename X, typename A>
-std::vector<A> convertWrappedCollectionToAidlUnchecked(
+static ConversionResult<std::vector<A>> convertWrappedCollectionToAidl(
         const std::vector<W>& xsdcWrapperTypeVec,
         std::function<const std::vector<X>&(const W&)> getInnerTypeVec,
-        std::function<A(const X&)> convertToAidl) {
+        std::function<ConversionResult<A>(const X&)> convertToAidl) {
     std::vector<A> resultAidlTypeVec;
     if (!xsdcWrapperTypeVec.empty()) {
         /*
@@ -98,21 +97,23 @@
          */
         resultAidlTypeVec.reserve(getInnerTypeVec(xsdcWrapperTypeVec[0]).size());
         for (const W& xsdcWrapperType : xsdcWrapperTypeVec) {
-            std::transform(getInnerTypeVec(xsdcWrapperType).begin(),
-                           getInnerTypeVec(xsdcWrapperType).end(),
-                           std::back_inserter(resultAidlTypeVec), convertToAidl);
+            for (const X& xsdcType : getInnerTypeVec(xsdcWrapperType)) {
+                resultAidlTypeVec.push_back(VALUE_OR_FATAL(convertToAidl(xsdcType)));
+            }
         }
     }
     return resultAidlTypeVec;
 }
 
 template <typename X, typename A>
-std::vector<A> convertCollectionToAidlUnchecked(const std::vector<X>& xsdcTypeVec,
-                                                std::function<A(const X&)> itemConversion) {
+static ConversionResult<std::vector<A>> convertCollectionToAidl(
+        const std::vector<X>& xsdcTypeVec,
+        std::function<ConversionResult<A>(const X&)> convertToAidl) {
     std::vector<A> resultAidlTypeVec;
     resultAidlTypeVec.reserve(xsdcTypeVec.size());
-    std::transform(xsdcTypeVec.begin(), xsdcTypeVec.end(), std::back_inserter(resultAidlTypeVec),
-                   itemConversion);
+    for (const X& xsdcType : xsdcTypeVec) {
+        resultAidlTypeVec.push_back(VALUE_OR_FATAL(convertToAidl(xsdcType)));
+    }
     return resultAidlTypeVec;
 }
 
diff --git a/audio/aidl/default/include/core-impl/XsdcConversion.h b/audio/aidl/default/include/core-impl/XsdcConversion.h
new file mode 100644
index 0000000..30dc8b6
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/XsdcConversion.h
@@ -0,0 +1,29 @@
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+
+#include <aidl/android/media/audio/common/AudioHalCapCriterion.h>
+#include <aidl/android/media/audio/common/AudioHalCapCriterionType.h>
+#include <aidl/android/media/audio/common/AudioHalVolumeCurve.h>
+#include <aidl/android/media/audio/common/AudioPort.h>
+#include <android_audio_policy_configuration.h>
+#include <android_audio_policy_configuration_enums.h>
+#include <android_audio_policy_engine_configuration.h>
+#include <media/AidlConversionUtil.h>
+
+#include "core-impl/Module.h"
+
+namespace aidl::android::hardware::audio::core::internal {
+
+ConversionResult<::aidl::android::media::audio::common::AudioHalCapCriterion>
+convertCapCriterionToAidl(
+        const ::android::audio::policy::engine::configuration::CriterionType& xsdcCriterion);
+ConversionResult<::aidl::android::media::audio::common::AudioHalCapCriterionType>
+convertCapCriterionTypeToAidl(
+        const ::android::audio::policy::engine::configuration::CriterionTypeType&
+                xsdcCriterionType);
+ConversionResult<::aidl::android::media::audio::common::AudioHalVolumeCurve::CurvePoint>
+convertCurvePointToAidl(const std::string& xsdcCurvePoint);
+ConversionResult<std::unique_ptr<Module::Configuration>> convertModuleConfigToAidl(
+        const ::android::audio::policy::configuration::Modules::Module& moduleConfig);
+}  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/main.cpp b/audio/aidl/default/main.cpp
index a0c0fab..6ab747d 100644
--- a/audio/aidl/default/main.cpp
+++ b/audio/aidl/default/main.cpp
@@ -16,21 +16,51 @@
 
 #include <cstdlib>
 #include <ctime>
-#include <sstream>
 #include <utility>
 #include <vector>
 
+#define LOG_TAG "AHAL_Main"
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android/binder_ibinder_platform.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
+#include "core-impl/AudioPolicyConfigXmlConverter.h"
+#include "core-impl/ChildInterface.h"
 #include "core-impl/Config.h"
 #include "core-impl/Module.h"
 
+using aidl::android::hardware::audio::core::ChildInterface;
 using aidl::android::hardware::audio::core::Config;
 using aidl::android::hardware::audio::core::Module;
+using aidl::android::hardware::audio::core::internal::AudioPolicyConfigXmlConverter;
+
+namespace {
+
+ChildInterface<Module> createModule(const std::string& name,
+                                    std::unique_ptr<Module::Configuration>&& config) {
+    ChildInterface<Module> result;
+    {
+        auto moduleType = Module::typeFromString(name);
+        if (!moduleType.has_value()) {
+            LOG(ERROR) << __func__ << ": module type \"" << name << "\" is not supported";
+            return result;
+        }
+        auto module = Module::createInstance(*moduleType, std::move(config));
+        if (module == nullptr) return result;
+        result = std::move(module);
+    }
+    const std::string moduleFqn = std::string().append(Module::descriptor).append("/").append(name);
+    binder_status_t status = AServiceManager_addService(result.getBinder(), moduleFqn.c_str());
+    if (status != STATUS_OK) {
+        LOG(ERROR) << __func__ << ": failed to register service for \"" << moduleFqn << "\"";
+        return ChildInterface<Module>();
+    }
+    return result;
+};
+
+}  // namespace
 
 int main() {
     // Random values are used in the implementation.
@@ -45,29 +75,27 @@
     // Guaranteed log for b/210919187 and logd_integration_test
     LOG(INFO) << "Init for Audio AIDL HAL";
 
+    AudioPolicyConfigXmlConverter audioPolicyConverter{
+            ::android::audio_get_audio_policy_config_file()};
+
     // Make the default config service
-    auto config = ndk::SharedRefBase::make<Config>();
-    const std::string configName = std::string() + Config::descriptor + "/default";
+    auto config = ndk::SharedRefBase::make<Config>(audioPolicyConverter);
+    const std::string configFqn = std::string().append(Config::descriptor).append("/default");
     binder_status_t status =
-            AServiceManager_addService(config->asBinder().get(), configName.c_str());
-    CHECK_EQ(STATUS_OK, status);
+            AServiceManager_addService(config->asBinder().get(), configFqn.c_str());
+    if (status != STATUS_OK) {
+        LOG(ERROR) << "failed to register service for \"" << configFqn << "\"";
+    }
 
     // Make modules
-    auto createModule = [](Module::Type type) {
-        auto module = Module::createInstance(type);
-        ndk::SpAIBinder moduleBinder = module->asBinder();
-        std::stringstream moduleName;
-        moduleName << Module::descriptor << "/" << type;
-        AIBinder_setMinSchedulerPolicy(moduleBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
-        binder_status_t status =
-                AServiceManager_addService(moduleBinder.get(), moduleName.str().c_str());
-        CHECK_EQ(STATUS_OK, status);
-        return std::make_pair(module, moduleBinder);
-    };
-    auto modules = {createModule(Module::Type::DEFAULT), createModule(Module::Type::R_SUBMIX),
-                    createModule(Module::Type::USB), createModule(Module::Type::STUB),
-                    createModule(Module::Type::BLUETOOTH)};
-    (void)modules;
+    std::vector<ChildInterface<Module>> moduleInstances;
+    auto configs(audioPolicyConverter.releaseModuleConfigs());
+    for (std::pair<std::string, std::unique_ptr<Module::Configuration>>& configPair : *configs) {
+        std::string name = configPair.first;
+        if (auto instance = createModule(name, std::move(configPair.second)); instance) {
+            moduleInstances.push_back(std::move(instance));
+        }
+    }
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
diff --git a/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp
index 9b2cb7c..99f2caf 100644
--- a/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp
+++ b/audio/aidl/default/noiseSuppression/NoiseSuppressionSw.cpp
@@ -65,7 +65,7 @@
         .common = {.id = {.type = getEffectTypeUuidNoiseSuppression(),
                           .uuid = getEffectImplUuidNoiseSuppressionSw(),
                           .proxy = std::nullopt},
-                   .flags = {.type = Flags::Type::INSERT,
+                   .flags = {.type = Flags::Type::PRE_PROC,
                              .insert = Flags::Insert::FIRST,
                              .volume = Flags::Volume::CTRL},
                    .name = NoiseSuppressionSw::kEffectName,
diff --git a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
index adea877..f8c775f 100644
--- a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
@@ -59,23 +59,22 @@
 
 ndk::ScopedAStatus ModuleRemoteSubmix::populateConnectedDevicePort(AudioPort* audioPort) {
     // Find the corresponding mix port and copy its profiles.
-    std::vector<AudioRoute> routes;
     // At this moment, the port has the same ID as the template port, see connectExternalDevice.
-    RETURN_STATUS_IF_ERROR(getAudioRoutesForAudioPort(audioPort->id, &routes));
+    std::vector<AudioRoute*> routes = getAudioRoutesForAudioPortImpl(audioPort->id);
     if (routes.empty()) {
         LOG(ERROR) << __func__ << ": no routes found for the port " << audioPort->toString();
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     const auto& route = *routes.begin();
     AudioPort mixPort;
-    if (route.sinkPortId == audioPort->id) {
-        if (route.sourcePortIds.empty()) {
-            LOG(ERROR) << __func__ << ": invalid route " << route.toString();
+    if (route->sinkPortId == audioPort->id) {
+        if (route->sourcePortIds.empty()) {
+            LOG(ERROR) << __func__ << ": invalid route " << route->toString();
             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
         }
-        RETURN_STATUS_IF_ERROR(getAudioPort(*route.sourcePortIds.begin(), &mixPort));
+        RETURN_STATUS_IF_ERROR(getAudioPort(*route->sourcePortIds.begin(), &mixPort));
     } else {
-        RETURN_STATUS_IF_ERROR(getAudioPort(route.sinkPortId, &mixPort));
+        RETURN_STATUS_IF_ERROR(getAudioPort(route->sinkPortId, &mixPort));
     }
     audioPort->profiles = mixPort.profiles;
     return ndk::ScopedAStatus::ok();
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index a2f0260..0de8574 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -40,7 +40,10 @@
         "general-tests",
         "vts",
     ],
-    srcs: [":effectCommonFile"],
+    srcs: [
+        ":effectCommonFile",
+        "TestUtils.cpp",
+    ],
 }
 
 cc_test {
diff --git a/audio/aidl/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
index af3597d..8f19547 100644
--- a/audio/aidl/vts/ModuleConfig.cpp
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -281,6 +281,22 @@
     return {};
 }
 
+std::vector<AudioPort> ModuleConfig::getRoutableMixPortsForDevicePort(const AudioPort& port) const {
+    std::set<int32_t> portIds;
+    for (const auto& route : mRoutes) {
+        if (port.id == route.sinkPortId) {
+            portIds.insert(route.sourcePortIds.begin(), route.sourcePortIds.end());
+        } else if (auto it = std::find(route.sourcePortIds.begin(), route.sourcePortIds.end(),
+                                       port.id);
+                   it != route.sourcePortIds.end()) {
+            portIds.insert(route.sinkPortId);
+        }
+    }
+    const bool isInput = port.flags.getTag() == AudioIoFlags::input;
+    return findMixPorts(isInput, false /*connectedOnly*/, false /*singlePort*/,
+                        [&portIds](const AudioPort& p) { return portIds.count(p.id) > 0; });
+}
+
 std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getNonRoutableSrcSinkPair(
         bool isInput) const {
     const auto mixPorts = getMixPorts(isInput, false /*connectedOnly*/);
diff --git a/audio/aidl/vts/ModuleConfig.h b/audio/aidl/vts/ModuleConfig.h
index 0cbf24d..b89adc0 100644
--- a/audio/aidl/vts/ModuleConfig.h
+++ b/audio/aidl/vts/ModuleConfig.h
@@ -103,6 +103,9 @@
     std::optional<aidl::android::media::audio::common::AudioPort>
     getSourceMixPortForConnectedDevice() const;
 
+    std::vector<aidl::android::media::audio::common::AudioPort> getRoutableMixPortsForDevicePort(
+            const aidl::android::media::audio::common::AudioPort& port) const;
+
     std::optional<SrcSinkPair> getNonRoutableSrcSinkPair(bool isInput) const;
     std::optional<SrcSinkPair> getRoutableSrcSinkPair(bool isInput) const;
     std::vector<SrcSinkGroup> getRoutableSrcSinkGroups(bool isInput) const;
diff --git a/audio/aidl/vts/TestUtils.cpp b/audio/aidl/vts/TestUtils.cpp
new file mode 100644
index 0000000..f018468
--- /dev/null
+++ b/audio/aidl/vts/TestUtils.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestUtils.h"
+
+#define LOG_TAG "VtsHalAudio_TestUtils"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::audio::common::testing {
+
+namespace detail {
+void TestExecutionTracer::OnTestStart(const ::testing::TestInfo& test_info) {
+    TraceTestState("Started", test_info);
+}
+
+void TestExecutionTracer::OnTestEnd(const ::testing::TestInfo& test_info) {
+    TraceTestState("Completed", test_info);
+}
+
+void TestExecutionTracer::OnTestPartResult(const ::testing::TestPartResult& result) {
+    LOG(INFO) << result;
+}
+
+void TestExecutionTracer::TraceTestState(const std::string& state,
+                                         const ::testing::TestInfo& test_info) {
+    LOG(INFO) << state << " " << test_info.test_suite_name() << "::" << test_info.name();
+}
+}
+}
\ No newline at end of file
diff --git a/audio/aidl/vts/TestUtils.h b/audio/aidl/vts/TestUtils.h
index b559669..191e980 100644
--- a/audio/aidl/vts/TestUtils.h
+++ b/audio/aidl/vts/TestUtils.h
@@ -22,11 +22,21 @@
 
 #include <android/binder_auto_utils.h>
 #include <gtest/gtest.h>
+#include <system/audio_aidl_utils.h>
 
 namespace android::hardware::audio::common::testing {
 
 namespace detail {
 
+class TestExecutionTracer : public ::testing::EmptyTestEventListener {
+  public:
+    void OnTestStart(const ::testing::TestInfo& test_info) override;
+    void OnTestEnd(const ::testing::TestInfo& test_info) override;
+    void OnTestPartResult(const ::testing::TestPartResult& result) override;
+  private:
+    static void TraceTestState(const std::string& state, const ::testing::TestInfo& test_info);
+};
+
 inline ::testing::AssertionResult assertIsOk(const char* expr, const ::ndk::ScopedAStatus& status) {
     if (status.isOk()) {
         return ::testing::AssertionSuccess();
diff --git a/audio/aidl/vts/VtsHalAECTargetTest.cpp b/audio/aidl/vts/VtsHalAECTargetTest.cpp
index 0354e3c..39168b1 100644
--- a/audio/aidl/vts/VtsHalAECTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAECTargetTest.cpp
@@ -34,6 +34,7 @@
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
 using aidl::android::hardware::audio::effect::Range;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 enum ParamName { PARAM_INSTANCE_NAME, PARAM_ECHO_DELAY, PARAM_MOBILE_MODE };
 using AECParamTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
@@ -178,6 +179,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
index 65c6a8f..6066025 100644
--- a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
@@ -28,6 +28,7 @@
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 enum ParamName {
     PARAM_INSTANCE_NAME,
@@ -189,6 +190,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
index 46a569e..8793e4c 100644
--- a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
@@ -29,6 +29,7 @@
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 enum ParamName {
     PARAM_INSTANCE_NAME,
@@ -194,6 +195,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 621d200..53e51f4 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -108,6 +108,7 @@
 using aidl::android::media::audio::common::Void;
 using android::hardware::audio::common::StreamLogic;
 using android::hardware::audio::common::StreamWorker;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 using ndk::enum_range;
 using ndk::ScopedAStatus;
 
@@ -1501,8 +1502,25 @@
                 << "port ID " << connectedPortId;
         EXPECT_EQ(portConnected.get(), connectedPort);
         const auto& portProfiles = connectedPort.profiles;
-        EXPECT_NE(0UL, portProfiles.size())
-                << "Connected port has no profiles: " << connectedPort.toString();
+        if (portProfiles.empty()) {
+            const auto routableMixPorts =
+                    moduleConfig->getRoutableMixPortsForDevicePort(connectedPort);
+            bool hasMixPortWithStaticProfile = false;
+            for (const auto& mixPort : routableMixPorts) {
+                const auto& mixPortProfiles = mixPort.profiles;
+                if (!mixPortProfiles.empty() &&
+                    !std::all_of(mixPortProfiles.begin(), mixPortProfiles.end(),
+                                 [](const auto& profile) {
+                                     return profile.format.type == AudioFormatType::DEFAULT;
+                                 })) {
+                    hasMixPortWithStaticProfile = true;
+                    break;
+                }
+            }
+            EXPECT_TRUE(hasMixPortWithStaticProfile)
+                    << "Connected port has no profiles and no routable mix ports with profiles: "
+                    << connectedPort.toString();
+        }
         const auto dynamicProfileIt =
                 std::find_if(portProfiles.begin(), portProfiles.end(), [](const auto& profile) {
                     return profile.format.type == AudioFormatType::DEFAULT;
@@ -1586,7 +1604,8 @@
         EXPECT_NE(portConfigsAfter.end(), afterIt)
                 << " port config ID " << c.id << " was removed by reset";
         if (afterIt != portConfigsAfter.end()) {
-            EXPECT_EQ(c, *afterIt);
+            EXPECT_TRUE(c == *afterIt)
+                    << "Expected: " << c.toString() << "; Actual: " << afterIt->toString();
         }
     }
 }
@@ -4426,21 +4445,6 @@
                          ::testing::ValuesIn(getRemoteSubmixModuleInstance()));
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioModuleRemoteSubmix);
 
-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);
     ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
index 225640e..523f20d 100644
--- a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -52,6 +52,7 @@
 using aidl::android::media::audio::common::AudioSource;
 using aidl::android::media::audio::common::AudioStreamType;
 using aidl::android::media::audio::common::AudioUuid;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 /// Effect factory testing.
 class EffectFactoryTest : public testing::TestWithParam<std::string> {
@@ -303,6 +304,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index 1876756..ca1cea9 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -51,6 +51,7 @@
 using aidl::android::media::audio::common::AudioDeviceType;
 using aidl::android::media::audio::common::AudioMode;
 using aidl::android::media::audio::common::AudioSource;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 enum ParamName { PARAM_INSTANCE_NAME };
 using EffectTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>>;
@@ -907,6 +908,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
index afddb84..2d9a233 100644
--- a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
@@ -32,7 +32,7 @@
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
 using aidl::android::hardware::audio::effect::Range;
-
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 /**
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
  * VtsAudioEffectTargetTest.
@@ -155,6 +155,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
index 7a2f31b..c01a9a2 100644
--- a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
@@ -28,7 +28,7 @@
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
-
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 /**
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
  * VtsAudioEffectTargetTest.
@@ -136,6 +136,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
index 5509c76..2650f49 100644
--- a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
+++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
@@ -36,6 +36,7 @@
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 /**
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
@@ -996,6 +997,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
index f2ef185..474b361 100644
--- a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
@@ -28,6 +28,7 @@
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 /**
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
@@ -536,6 +537,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
index 37e7c0a..09396d1 100644
--- a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
@@ -46,6 +46,7 @@
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 /**
  * Here we focus on specific effect (equalizer) parameter checking, general IEffect interfaces
@@ -220,6 +221,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
index b33234b..5a32398 100644
--- a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
@@ -33,6 +33,7 @@
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 /**
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
@@ -431,6 +432,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
index cbb80a9..925f9ec 100644
--- a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
@@ -30,28 +30,21 @@
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::LoudnessEnhancer;
 using aidl::android::hardware::audio::effect::Parameter;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
-/**
- * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
- * VtsAudioEffectTargetTest.
- */
-enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
-using LoudnessEnhancerParamTestParam =
-        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
+static constexpr float kMaxAudioSample = 1;
+static constexpr int kZeroGain = 0;
+static constexpr int kMaxGain = std::numeric_limits<int>::max();
+static constexpr int kMinGain = std::numeric_limits<int>::min();
+static constexpr float kAbsError = 0.0001;
 
 // Every int 32 bit value is a valid gain, so testing the corner cases and one regular value.
 // TODO : Update the test values once range/capability is updated by implementation.
-const std::vector<int> kGainMbValues = {std::numeric_limits<int>::min(), 100,
-                                        std::numeric_limits<int>::max()};
+static const std::vector<int> kGainMbValues = {kMinGain, -100, -50, kZeroGain, 50, 100, kMaxGain};
 
-class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhancerParamTestParam>,
-                                  public EffectHelper {
+class LoudnessEnhancerEffectHelper : public EffectHelper {
   public:
-    LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
-        std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
-    }
-
-    void SetUp() override {
+    void SetUpLoudnessEnhancer() {
         ASSERT_NE(nullptr, mFactory);
         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
@@ -59,13 +52,14 @@
         Parameter::Common common = EffectHelper::createParamCommon(
                 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
                 kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
-        IEffect::OpenEffectReturn ret;
-        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
+        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE));
         ASSERT_NE(nullptr, mEffect);
     }
-    void TearDown() override {
+
+    void TearDownLoudnessEnhancer() {
         ASSERT_NO_FATAL_FAILURE(close(mEffect));
         ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+        mOpenEffectReturn = IEffect::OpenEffectReturn{};
     }
 
     Parameter::Specific getDefaultParamSpecific() {
@@ -75,52 +69,230 @@
         return specific;
     }
 
-    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
-    std::shared_ptr<IFactory> mFactory;
-    std::shared_ptr<IEffect> mEffect;
-    Descriptor mDescriptor;
-    int mParamGainMb = 0;
+    Parameter createLoudnessParam(int gainMb) {
+        LoudnessEnhancer le;
+        le.set<LoudnessEnhancer::gainMb>(gainMb);
+        Parameter param;
+        Parameter::Specific specific;
+        specific.set<Parameter::Specific::loudnessEnhancer>(le);
+        param.set<Parameter::specific>(specific);
+        return param;
+    }
 
-    void SetAndGetParameters() {
-        for (auto& it : mTags) {
-            auto& tag = it.first;
-            auto& le = it.second;
-
-            // set parameter
-            Parameter expectParam;
-            Parameter::Specific specific;
-            specific.set<Parameter::Specific::loudnessEnhancer>(le);
-            expectParam.set<Parameter::specific>(specific);
-            // All values are valid, set parameter should succeed
-            EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectParam)) << expectParam.toString();
-
-            // get parameter
-            Parameter getParam;
-            Parameter::Id id;
-            LoudnessEnhancer::Id leId;
-            leId.set<LoudnessEnhancer::Id::commonTag>(tag);
-            id.set<Parameter::Id::loudnessEnhancerTag>(leId);
-            EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
-
-            EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString()
-                                             << "\ngetParam:" << getParam.toString();
+    binder_exception_t isGainValid(int gainMb) {
+        LoudnessEnhancer le;
+        le.set<LoudnessEnhancer::gainMb>(gainMb);
+        if (isParameterValid<LoudnessEnhancer, Range::loudnessEnhancer>(le, mDescriptor)) {
+            return EX_NONE;
+        } else {
+            return EX_ILLEGAL_ARGUMENT;
         }
     }
 
-    void addGainMbParam(int gainMb) {
-        LoudnessEnhancer le;
-        le.set<LoudnessEnhancer::gainMb>(gainMb);
-        mTags.push_back({LoudnessEnhancer::gainMb, le});
+    void setParameters(int gain, binder_exception_t expected) {
+        // set parameter
+        auto param = createLoudnessParam(gain);
+        EXPECT_STATUS(expected, mEffect->setParameter(param)) << param.toString();
     }
 
-  private:
-    std::vector<std::pair<LoudnessEnhancer::Tag, LoudnessEnhancer>> mTags;
-    void CleanUp() { mTags.clear(); }
+    void validateParameters(int gain) {
+        // get parameter
+        LoudnessEnhancer::Id leId;
+        Parameter getParam;
+        Parameter::Id id;
+
+        LoudnessEnhancer::Tag tag(LoudnessEnhancer::gainMb);
+        leId.set<LoudnessEnhancer::Id::commonTag>(tag);
+        id.set<Parameter::Id::loudnessEnhancerTag>(leId);
+        EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+        auto expectedParam = createLoudnessParam(gain);
+        EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString()
+                                           << "\ngetParam:" << getParam.toString();
+    }
+
+    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+    IEffect::OpenEffectReturn mOpenEffectReturn;
+    std::shared_ptr<IFactory> mFactory;
+    std::shared_ptr<IEffect> mEffect;
+    Descriptor mDescriptor;
+};
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEffectTargetTest.
+ */
+enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
+using LoudnessEnhancerParamTestParam =
+        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
+
+class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhancerParamTestParam>,
+                                  public LoudnessEnhancerEffectHelper {
+  public:
+    LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
+        std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+    }
+
+    void SetUp() override { SetUpLoudnessEnhancer(); }
+    void TearDown() override { TearDownLoudnessEnhancer(); }
+    int mParamGainMb = 0;
 };
 
 TEST_P(LoudnessEnhancerParamTest, SetAndGetGainMb) {
-    EXPECT_NO_FATAL_FAILURE(addGainMbParam(mParamGainMb));
-    SetAndGetParameters();
+    binder_exception_t expected = isGainValid(mParamGainMb);
+    setParameters(mParamGainMb, expected);
+    if (expected == EX_NONE) {
+        validateParameters(mParamGainMb);
+    }
+}
+
+using LoudnessEnhancerDataTestParam = std::pair<std::shared_ptr<IFactory>, Descriptor>;
+
+class LoudnessEnhancerDataTest : public ::testing::TestWithParam<LoudnessEnhancerDataTestParam>,
+                                 public LoudnessEnhancerEffectHelper {
+  public:
+    LoudnessEnhancerDataTest() {
+        std::tie(mFactory, mDescriptor) = GetParam();
+        generateInputBuffer();
+        mOutputBuffer.resize(kBufferSize);
+    }
+
+    void SetUp() override {
+        SetUpLoudnessEnhancer();
+
+        // Creating AidlMessageQueues
+        mStatusMQ = std::make_unique<EffectHelper::StatusMQ>(mOpenEffectReturn.statusMQ);
+        mInputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.inputDataMQ);
+        mOutputMQ = std::make_unique<EffectHelper::DataMQ>(mOpenEffectReturn.outputDataMQ);
+    }
+
+    void TearDown() override { TearDownLoudnessEnhancer(); }
+
+    // Fill inputBuffer with random values between -kMaxAudioSample to kMaxAudioSample
+    void generateInputBuffer() {
+        for (size_t i = 0; i < kBufferSize; i++) {
+            mInputBuffer.push_back(((static_cast<float>(std::rand()) / RAND_MAX) * 2 - 1) *
+                                   kMaxAudioSample);
+        }
+    }
+
+    // Add gains to the mInputBuffer and store processed output to mOutputBuffer
+    void processAndWriteToOutput() {
+        // Check AidlMessageQueues are not null
+        ASSERT_TRUE(mStatusMQ->isValid());
+        ASSERT_TRUE(mInputMQ->isValid());
+        ASSERT_TRUE(mOutputMQ->isValid());
+
+        // Enabling the process
+        ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+        ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+
+        // Write from buffer to message queues and calling process
+        EXPECT_NO_FATAL_FAILURE(EffectHelper::writeToFmq(mStatusMQ, mInputMQ, mInputBuffer));
+
+        // Read the updated message queues into buffer
+        EXPECT_NO_FATAL_FAILURE(EffectHelper::readFromFmq(mStatusMQ, 1, mOutputMQ,
+                                                          mOutputBuffer.size(), mOutputBuffer));
+
+        // Disable the process
+        ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+    }
+
+    void assertGreaterGain(const std::vector<float>& first, const std::vector<float>& second) {
+        for (size_t i = 0; i < first.size(); i++) {
+            if (first[i] != 0) {
+                ASSERT_GT(abs(first[i]), abs(second[i]));
+
+            } else {
+                ASSERT_EQ(first[i], second[i]);
+            }
+        }
+    }
+
+    void assertSequentialGains(const std::vector<int>& gainValues, bool isIncreasing) {
+        std::vector<float> baseOutput(kBufferSize);
+
+        // Process a reference output buffer with 0 gain which gives compressed input values
+        binder_exception_t expected;
+        expected = isGainValid(kZeroGain);
+        ASSERT_EQ(expected, EX_NONE);
+        setParameters(kZeroGain, expected);
+        ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
+        baseOutput = mOutputBuffer;
+
+        // Compare the outputs for increasing gain
+        for (int gain : gainValues) {
+            // Setting the parameters
+            binder_exception_t expected = isGainValid(gain);
+            if (expected != EX_NONE) {
+                GTEST_SKIP() << "Gains not supported.";
+            }
+            setParameters(gain, expected);
+            ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
+
+            // Compare the mOutputBuffer values with baseOutput and update it
+            if (isIncreasing) {
+                ASSERT_NO_FATAL_FAILURE(assertGreaterGain(mOutputBuffer, baseOutput));
+            } else {
+                ASSERT_NO_FATAL_FAILURE(assertGreaterGain(baseOutput, mOutputBuffer));
+            }
+
+            baseOutput = mOutputBuffer;
+        }
+    }
+
+    std::unique_ptr<StatusMQ> mStatusMQ;
+    std::unique_ptr<DataMQ> mInputMQ;
+    std::unique_ptr<DataMQ> mOutputMQ;
+
+    std::vector<float> mInputBuffer;
+    std::vector<float> mOutputBuffer;
+    static constexpr float kBufferSize = 128;
+};
+
+TEST_P(LoudnessEnhancerDataTest, IncreasingGains) {
+    static const std::vector<int> kIncreasingGains = {50, 100};
+
+    assertSequentialGains(kIncreasingGains, true /*isIncreasing*/);
+}
+
+TEST_P(LoudnessEnhancerDataTest, DecreasingGains) {
+    static const std::vector<int> kDecreasingGains = {-50, -100};
+
+    assertSequentialGains(kDecreasingGains, false /*isIncreasing*/);
+}
+
+TEST_P(LoudnessEnhancerDataTest, MinimumGain) {
+    // Setting the parameters
+    binder_exception_t expected = isGainValid(kMinGain);
+    if (expected != EX_NONE) {
+        GTEST_SKIP() << "Minimum integer value not supported";
+    }
+    setParameters(kMinGain, expected);
+    ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
+
+    // Validate that mOutputBuffer has 0 values for INT_MIN gain
+    for (size_t i = 0; i < mOutputBuffer.size(); i++) {
+        ASSERT_FLOAT_EQ(mOutputBuffer[i], 0);
+    }
+}
+
+TEST_P(LoudnessEnhancerDataTest, MaximumGain) {
+    // Setting the parameters
+    binder_exception_t expected = isGainValid(kMaxGain);
+    if (expected != EX_NONE) {
+        GTEST_SKIP() << "Maximum integer value not supported";
+    }
+    setParameters(kMaxGain, expected);
+    ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
+
+    // Validate that mOutputBuffer reaches to kMaxAudioSample for INT_MAX gain
+    for (size_t i = 0; i < mOutputBuffer.size(); i++) {
+        if (mInputBuffer[i] != 0) {
+            EXPECT_NEAR(kMaxAudioSample, abs(mOutputBuffer[i]), kAbsError);
+        } else {
+            ASSERT_EQ(mOutputBuffer[i], mInputBuffer[i]);
+        }
+    }
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -139,8 +311,23 @@
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerParamTest);
 
+INSTANTIATE_TEST_SUITE_P(
+        LoudnessEnhancerTest, LoudnessEnhancerDataTest,
+        testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+                IFactory::descriptor, getEffectTypeUuidLoudnessEnhancer())),
+        [](const testing::TestParamInfo<LoudnessEnhancerDataTest::ParamType>& info) {
+            auto descriptor = info.param;
+            std::string name = getPrefix(descriptor.second);
+            std::replace_if(
+                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+            return name;
+        });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerDataTest);
+
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalNSTargetTest.cpp b/audio/aidl/vts/VtsHalNSTargetTest.cpp
index 624d5d2..12d56b0 100644
--- a/audio/aidl/vts/VtsHalNSTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalNSTargetTest.cpp
@@ -32,6 +32,7 @@
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::NoiseSuppression;
 using aidl::android::hardware::audio::effect::Parameter;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 enum ParamName { PARAM_INSTANCE_NAME, PARAM_LEVEL, PARAM_TYPE };
 using NSParamTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
@@ -171,6 +172,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
index 3056c6c..57eda09 100644
--- a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
@@ -29,6 +29,7 @@
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
 using aidl::android::hardware::audio::effect::PresetReverb;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 /**
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
@@ -147,6 +148,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
index 07a9fa4..3e39d3a 100644
--- a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
@@ -28,6 +28,7 @@
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
 using aidl::android::hardware::audio::effect::Virtualizer;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 /**
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
@@ -151,6 +152,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
index 903ba69..1b8352b 100644
--- a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -31,6 +31,7 @@
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
 using aidl::android::hardware::audio::effect::Visualizer;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 /**
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
@@ -207,6 +208,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
index 0b5b9fc..257100b 100644
--- a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
@@ -28,6 +28,7 @@
 using aidl::android::hardware::audio::effect::IFactory;
 using aidl::android::hardware::audio::effect::Parameter;
 using aidl::android::hardware::audio::effect::Volume;
+using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
 /**
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
@@ -159,6 +160,7 @@
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
     ABinderProcess_setThreadPoolMaxThreadCount(1);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
diff --git a/audio/common/all-versions/test/utility/src/ValidateXml.cpp b/audio/common/all-versions/test/utility/src/ValidateXml.cpp
index 4d6f003..b7e685b 100644
--- a/audio/common/all-versions/test/utility/src/ValidateXml.cpp
+++ b/audio/common/all-versions/test/utility/src/ValidateXml.cpp
@@ -19,6 +19,7 @@
 
 #include <numeric>
 
+#include <libxml/parser.h>
 #define LIBXML_SCHEMAS_ENABLED
 #include <libxml/xmlschemastypes.h>
 #define LIBXML_XINCLUDE_ENABLED
diff --git a/audio/common/all-versions/test/utility/tests/utility_tests.cpp b/audio/common/all-versions/test/utility/tests/utility_tests.cpp
index c523066..c2bcfbc 100644
--- a/audio/common/all-versions/test/utility/tests/utility_tests.cpp
+++ b/audio/common/all-versions/test/utility/tests/utility_tests.cpp
@@ -70,6 +70,7 @@
 std::string substitute(const char* fmt, const char* param) {
     std::string buffer(static_cast<size_t>(strlen(fmt) + strlen(param)), '\0');
     snprintf(buffer.data(), buffer.size(), fmt, param);
+    buffer.resize(strlen(buffer.c_str()));
     return buffer;
 }
 
diff --git a/authsecret/aidl/default/Android.bp b/authsecret/aidl/default/Android.bp
index 7e6e48b..91f4fae 100644
--- a/authsecret/aidl/default/Android.bp
+++ b/authsecret/aidl/default/Android.bp
@@ -55,23 +55,12 @@
     installable: false,
 }
 
-apex_key {
-    name: "com.android.hardware.authsecret.key",
-    public_key: "com.android.hardware.authsecret.avbpubkey",
-    private_key: "com.android.hardware.authsecret.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.authsecret.certificate",
-    certificate: "com.android.hardware.authsecret",
-}
-
 apex {
     name: "com.android.hardware.authsecret",
     manifest: "manifest.json",
     file_contexts: "file_contexts",
-    key: "com.android.hardware.authsecret.key",
-    certificate: ":com.android.hardware.authsecret.certificate",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
     updatable: false,
     vendor: true,
 
diff --git a/authsecret/aidl/default/com.android.hardware.authsecret.avbpubkey b/authsecret/aidl/default/com.android.hardware.authsecret.avbpubkey
deleted file mode 100644
index 2fb5f0b..0000000
--- a/authsecret/aidl/default/com.android.hardware.authsecret.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/authsecret/aidl/default/com.android.hardware.authsecret.pem b/authsecret/aidl/default/com.android.hardware.authsecret.pem
deleted file mode 100644
index 644868c..0000000
--- a/authsecret/aidl/default/com.android.hardware.authsecret.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-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
-hUHo4XX1/r2CDceZTmOjaZP/MQOJ
------END PRIVATE KEY-----
diff --git a/authsecret/aidl/default/com.android.hardware.authsecret.pk8 b/authsecret/aidl/default/com.android.hardware.authsecret.pk8
deleted file mode 100644
index 1453366..0000000
--- a/authsecret/aidl/default/com.android.hardware.authsecret.pk8
+++ /dev/null
Binary files differ
diff --git a/authsecret/aidl/default/com.android.hardware.authsecret.x509.pem b/authsecret/aidl/default/com.android.hardware.authsecret.x509.pem
deleted file mode 100644
index 71fe854..0000000
--- a/authsecret/aidl/default/com.android.hardware.authsecret.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF4zCCA8sCFH8r8uUt7ZiBGNZm/OxNbzMI34N3MA0GCSqGSIb3DQEBCwUAMIGs
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEoMCYGA1UEAwwfY29t
-LmFuZHJvaWQuaGFyZHdhcmUuYXV0aHNlY3JldDAgFw0yMzA4MTgwNzA3MDFaGA80
-NzYxMDcxNDA3MDcwMVowgawxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9y
-bmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAw
-DgYDVQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQu
-Y29tMSgwJgYDVQQDDB9jb20uYW5kcm9pZC5oYXJkd2FyZS5hdXRoc2VjcmV0MIIC
-IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1+ml99ip2TVpYdJXxqVnizLg
-/DAnOUy5rZE+mCpjua1zyHl7GFFnseq6GO5wftptWekcC9fVSPxg1YS+RVduRcNz
-rt3mCsJ60DexaHrElITc1GCC1vzyt9cg6UtmdYg+OXSPlfWZE2T7OLfGWrhU56El
-IFt1eQDu5RDBOHZ2/N30KmKXv3yhpdl5un/kaC6q6p1PPih0aYXT2PrHsyN17wBl
-smhhpWNg/OAzFhWKwFcSTLMCOAI+pjqWKqXmjQ1awBly+lLAtHEBxxEUDMD6Z4lv
-2OGftL9bdseb1Wbj2bgj22bkfwWj5Yu77ilz5H27aLxQouQsmSfBkVgLq6seQMzd
-ovg+MOFb9iyWgcWkGg7eKdSzjfzCKQ/d2GOxEqwGofEYUOxYM1+a0Fnb7vUtgT/v
-I4tJCgXxAMFtsYGySC+gBhNx7vqLfo/8gtcZjJL6PRtRJ2V7hF9x3xKFa2/6qOLn
-UD/R5z+uwzaEqom+AmmmKNdWtn58nBns7EGq/3KVPcb7CSi9Xf6CCJiV+AmRaBSx
-2CtLt1fBX46LM3bV+iw7ZFAYAAXE3j6FgpM/PlozQjl61TuomHQP1ILmu/988tiF
-FMbuRH6mI0u4VOkDBUg9lxmjr0uAVmysWmzkRrAKydzedsuG5WG6hy2ZcD+lCV05
-JzvE6pB65OaIEPB5cMECAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAozFo1vOIy/Js
-/EU5oRtSGSIoWCNIn7EYQ68jVHQk2ZhklVH2jW+6WVGmreOjPz5iWeDb0fC4KVtH
-MPXJ1Vd+GfvDysrnW5mDBzlI1O2xv/BWYeHt+RFWghhH/NFHaTQqDJpdOZXMZM4F
-dwFefxLchcXftE9jihHJXJ4k0cxC03Kpd0caZE7b67W1YQdJhU9mZx6CP1A3MdWU
-f48QIsmHgejkihtGNDRheBRzNdpHPhdOjYIWhOeAHh/xnm7PVZBMXmZeNW7MrAS0
-+lN99r7Xj3eqtSdrMrrob845PWYsATA/a8ouUuTT7812fl8tZx69xb8wV5hNztDj
-srOxxJbjt1uwcSp67f2K91D97CQuMMPnOt1oFEXT+5QtLEiybXKfkshwO7VVDoIg
-owMLoKIiA2Xr+rZn7CEBeTrqQuRJfJEI+k/49zg2zWQIKGQAz8iaO0l95Hk5kPTE
-A5i9qxhn0UqC6a4Dkj8ybQOACzVA06IsbbYdprfzURQHjcUiSrEzjrwWxkkX/9El
-Z0CJAtkXx4pMxo5s6zt26ZPC3cxWB7aageWSC4xDbKuQP5VCNVg1nWymg6nF4Xk9
-d7n7yvSNH6fAZrpmZo7o7CBxCb4QN8j7TpyuaPd7nzyCyR6aGbh7fz8xksukvj6w
-ZSbAAy5uw4hyUwTTpyPyw+qQxI7O/PU=
------END CERTIFICATE-----
diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index 9c72acd..580b0ee 100644
--- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -66,8 +66,8 @@
 
         ASSERT_NE(pEnumerator.get(), nullptr);
 
-        // "default" is reserved for EVS manager.
-        constexpr static char kEvsManagerName[] = "default";
+        // "legacy_sw/0" is reserved for EVS manager v1.0 implementation.
+        constexpr static char kEvsManagerName[] = "legacy_sw/0";
         mIsHwModule = service_name.compare(kEvsManagerName);
     }
 
@@ -364,8 +364,14 @@
 TEST_P(EvsHidlTest, CameraStreamBuffering) {
     ALOGI("Starting CameraStreamBuffering test");
 
-    // Arbitrary constant (should be > 1 and not too big)
-    static const unsigned int kBuffersToHold = 2;
+    // Maximum number of frames in flight this test case will attempt. This test
+    // case chooses an arbitrary number that is large enough to run a camera
+    // pipeline for a single client.
+    constexpr unsigned int kMaxBuffersToHold = 20;
+
+    // Initial value for setMaxFramesInFlight() call. This number should be
+    // greater than 1.
+    unsigned int buffersToHold = 2;
 
     // Get the camera list
     loadCameraList();
@@ -381,9 +387,16 @@
         EXPECT_EQ(EvsResult::BUFFER_NOT_AVAILABLE, badResult);
 
         // Now ask for exactly two buffers in flight as we'll test behavior in that case
-        Return<EvsResult> goodResult = pCam->setMaxFramesInFlight(kBuffersToHold);
-        EXPECT_EQ(EvsResult::OK, goodResult);
+        // Find the minimum number of buffers to run a target camera.
+        while (buffersToHold < kMaxBuffersToHold) {
+            Return<EvsResult> goodResult = pCam->setMaxFramesInFlight(buffersToHold);
+            if (goodResult == EvsResult::OK) {
+                break;
+            }
 
+            ++buffersToHold;
+        }
+        EXPECT_LE(buffersToHold, kMaxBuffersToHold);
 
         // Set up a frame receiver object which will fire up its own thread.
         sp<FrameHandler> frameHandler = new FrameHandler(pCam, cam,
@@ -399,7 +412,7 @@
         sleep(2);   // 1 second should be enough for at least 5 frames to be delivered worst case
         unsigned framesReceived = 0;
         frameHandler->getFramesCounters(&framesReceived, nullptr);
-        ASSERT_EQ(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
+        ASSERT_EQ(buffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
 
 
         // Give back one buffer
@@ -410,7 +423,7 @@
         // filled since we require 10fps minimum -- but give a 10% allowance just in case.
         usleep(110 * kMillisecondsToMicroseconds);
         frameHandler->getFramesCounters(&framesReceived, nullptr);
-        EXPECT_EQ(kBuffersToHold+1, framesReceived) << "Stream should've resumed";
+        EXPECT_EQ(buffersToHold+1, framesReceived) << "Stream should've resumed";
 
         // Even when the camera pointer goes out of scope, the FrameHandler object will
         // keep the stream alive unless we tell it to shutdown.
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 9c8bfc4..03f256e 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -534,8 +534,14 @@
 TEST_P(EvsHidlTest, CameraStreamBuffering) {
     LOG(INFO) << "Starting CameraStreamBuffering test";
 
-    // Arbitrary constant (should be > 1 and not too big)
-    static const unsigned int kBuffersToHold = 2;
+    // Maximum number of frames in flight this test case will attempt. This test
+    // case chooses an arbitrary number that is large enough to run a camera
+    // pipeline for a single client.
+    constexpr unsigned int kMaxBuffersToHold = 20;
+
+    // Initial value for setMaxFramesInFlight() call. This number should be
+    // greater than 1.
+    unsigned int buffersToHold = 2;
 
     // Get the camera list
     loadCameraList();
@@ -567,9 +573,15 @@
         EXPECT_EQ(EvsResult::BUFFER_NOT_AVAILABLE, badResult);
 
         // Now ask for exactly two buffers in flight as we'll test behavior in that case
-        Return<EvsResult> goodResult = pCam->setMaxFramesInFlight(kBuffersToHold);
-        EXPECT_EQ(EvsResult::OK, goodResult);
+        while (buffersToHold < kMaxBuffersToHold) {
+            Return<EvsResult> goodResult = pCam->setMaxFramesInFlight(buffersToHold);
+            if (goodResult == EvsResult::OK) {
+                break;
+            }
 
+            ++buffersToHold;
+        }
+        EXPECT_LE(buffersToHold, kMaxBuffersToHold);
 
         // Set up a frame receiver object which will fire up its own thread.
         sp<FrameHandler> frameHandler = new FrameHandler(pCam, cam,
@@ -585,7 +597,7 @@
         sleep(1);   // 1 second should be enough for at least 5 frames to be delivered worst case
         unsigned framesReceived = 0;
         frameHandler->getFramesCounters(&framesReceived, nullptr);
-        ASSERT_EQ(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
+        ASSERT_EQ(buffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
 
 
         // Give back one buffer
@@ -596,7 +608,7 @@
         // filled since we require 10fps minimum -- but give a 10% allowance just in case.
         usleep(110 * kMillisecondsToMicroseconds);
         frameHandler->getFramesCounters(&framesReceived, nullptr);
-        EXPECT_EQ(kBuffersToHold+1, framesReceived) << "Stream should've resumed";
+        EXPECT_EQ(buffersToHold+1, framesReceived) << "Stream should've resumed";
 
         // Even when the camera pointer goes out of scope, the FrameHandler object will
         // keep the stream alive unless we tell it to shutdown.
diff --git a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
index 8bcad1e..910ae7c 100644
--- a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
+++ b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
@@ -115,6 +115,9 @@
 };
 
 class VtsHalAutomotiveVehicleTargetTest : public testing::TestWithParam<ServiceDescriptor> {
+  protected:
+    bool checkIsSupported(int32_t propertyId);
+
   public:
     void verifyProperty(VehicleProperty propId, VehiclePropertyAccess access,
                         VehiclePropertyChangeMode changeMode, VehiclePropertyGroup group,
@@ -155,7 +158,7 @@
     }
 }
 
-// Test getAllPropConfig() returns at least 4 property configs.
+// Test getAllPropConfigs() returns at least 1 property configs.
 TEST_P(VtsHalAutomotiveVehicleTargetTest, getAllPropConfigs) {
     ALOGD("VtsHalAutomotiveVehicleTargetTest::getAllPropConfigs");
 
@@ -163,25 +166,31 @@
 
     ASSERT_TRUE(result.ok()) << "Failed to get all property configs, error: "
                              << result.error().message();
-    ASSERT_GE(result.value().size(), 4u) << StringPrintf(
-            "Expect to get at least 4 property configs, got %zu", result.value().size());
+    ASSERT_GE(result.value().size(), 1u)
+          << StringPrintf("Expect to get at least 1 property config, got %zu",
+                          result.value().size());
 }
 
-// Test getPropConfigs() can query all properties listed in CDD.
-TEST_P(VtsHalAutomotiveVehicleTargetTest, getRequiredPropConfigs) {
+// Test getPropConfigs() can query properties returned by getAllPropConfigs.
+TEST_P(VtsHalAutomotiveVehicleTargetTest, getPropConfigsWithValidProps) {
     ALOGD("VtsHalAutomotiveVehicleTargetTest::getRequiredPropConfigs");
 
-    // Check the properties listed in CDD
-    std::vector<int32_t> properties = {
-            toInt(VehicleProperty::GEAR_SELECTION), toInt(VehicleProperty::NIGHT_MODE),
-            toInt(VehicleProperty::PARKING_BRAKE_ON), toInt(VehicleProperty::PERF_VEHICLE_SPEED)};
+    std::vector<int32_t> properties;
+    auto result = mVhalClient->getAllPropConfigs();
 
-    auto result = mVhalClient->getPropConfigs(properties);
+    ASSERT_TRUE(result.ok()) << "Failed to get all property configs, error: "
+                             << result.error().message();
+    for (const auto& cfgPtr : result.value()) {
+        properties.push_back(cfgPtr->getPropId());
+    }
+
+    result = mVhalClient->getPropConfigs(properties);
 
     ASSERT_TRUE(result.ok()) << "Failed to get required property config, error: "
                              << result.error().message();
-    ASSERT_EQ(result.value().size(), 4u)
-            << StringPrintf("Expect to get exactly 4 configs, got %zu", result.value().size());
+    ASSERT_EQ(result.value().size(), properties.size())
+          << StringPrintf("Expect to get exactly %zu configs, got %zu",
+                          properties.size(), result.value().size());
 }
 
 // Test getPropConfig() with an invalid propertyId returns an error code.
@@ -200,6 +209,9 @@
     ALOGD("VtsHalAutomotiveVehicleTargetTest::get");
 
     int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
+    if (!checkIsSupported(propId)) {
+        GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
+    }
     auto result = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(propId));
 
     ASSERT_TRUE(result.ok()) << StringPrintf("Failed to get value for property: %" PRId32
@@ -285,6 +297,10 @@
     ALOGD("VtsHalAutomotiveVehicleTargetTest::setNotWritableProp");
 
     int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
+    if (!checkIsSupported(propId)) {
+        GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
+    }
+
     auto getValueResult = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(propId));
     ASSERT_TRUE(getValueResult.ok())
             << StringPrintf("Failed to get value for property: %" PRId32 ", error: %s", propId,
@@ -325,6 +341,9 @@
     ALOGD("VtsHalAutomotiveVehicleTargetTest::subscribeAndUnsubscribe");
 
     int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
+    if (!checkIsSupported(propId)) {
+        GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
+    }
 
     auto propConfigsResult = mVhalClient->getPropConfigs({propId});
 
@@ -414,6 +433,9 @@
     }
 
     int32_t propId = toInt(VehicleProperty::PARKING_BRAKE_ON);
+    if (!checkIsSupported(propId)) {
+        GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
+    }
     auto prop = mVhalClient->createHalPropValue(propId);
 
     auto result = mVhalClient->getValueSync(*prop);
@@ -865,6 +887,11 @@
                    VehicleArea::GLOBAL, VehiclePropertyType::INT32);
 }
 
+bool VtsHalAutomotiveVehicleTargetTest::checkIsSupported(int32_t propertyId) {
+    auto result = mVhalClient->getPropConfigs({propertyId});
+    return result.ok();
+}
+
 std::vector<ServiceDescriptor> getDescriptors() {
     std::vector<ServiceDescriptor> descriptors;
     for (std::string name : getAidlHalInstanceNames(IVehicle::descriptor)) {
diff --git a/biometrics/face/aidl/default/apex/Android.bp b/biometrics/face/aidl/default/apex/Android.bp
index 2f39a08..0ae1463 100644
--- a/biometrics/face/aidl/default/apex/Android.bp
+++ b/biometrics/face/aidl/default/apex/Android.bp
@@ -16,27 +16,14 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-apex_key {
-    name: "com.android.hardware.biometrics.face.key",
-    public_key: "com.android.hardware.biometrics.face.avbpubkey",
-    private_key: "com.android.hardware.biometrics.face.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.biometrics.face.certificate",
-    certificate: "com.android.hardware.biometrics.face",
-}
-
 apex {
     name: "com.android.hardware.biometrics.face",
     manifest: "manifest.json",
     file_contexts: "file_contexts",
-    key: "com.android.hardware.biometrics.face.key",
-    certificate: ":com.android.hardware.biometrics.face.certificate",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
     updatable: false,
-
     vendor: true,
-    use_vndk_as_stable: true,
 
     binaries: [
         // hal
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.avbpubkey b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.avbpubkey
deleted file mode 100644
index 9f358ff..0000000
--- a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pem b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pem
deleted file mode 100644
index ad8f57d..0000000
--- a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-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
-ZJpVwCxgxAOagrQtvwdedbmvChAfGA==
------END PRIVATE KEY-----
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pk8 b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pk8
deleted file mode 100644
index af0ff4e..0000000
--- a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.pk8
+++ /dev/null
Binary files differ
diff --git a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.x509.pem b/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.x509.pem
deleted file mode 100644
index 3dc37ff..0000000
--- a/biometrics/face/aidl/default/apex/com.android.hardware.biometrics.face.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF7TCCA9UCFCmJBOOYRVUgdy8vKm8OQd0ii2pPMA0GCSqGSIb3DQEBCwUAMIGx
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEtMCsGA1UEAwwkY29t
-LmFuZHJvaWQuaGFyZHdhcmUuYmlvbWV0cmljcy5mYWNlMCAXDTIzMDUyNTA2NDIw
-MFoYDzQ3NjEwNDIwMDY0MjAwWjCBsTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh
-bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJv
-aWQxEDAOBgNVBAsMB0FuZHJvaWQxIjAgBgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5k
-cm9pZC5jb20xLTArBgNVBAMMJGNvbS5hbmRyb2lkLmhhcmR3YXJlLmJpb21ldHJp
-Y3MuZmFjZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPadnCNPEvKN
-HxACZt3C+tE2rga6gZ1pxfvlwGo1UY9yAxcQjL22SW93OA6R3de5uvQUbHh7b9g5
-AbNYcRnxOMiuUK2XSGWGDscxuGpQVCph4G1rXCOtbTmz1Zb42vQLCCQHHyxzI7ZE
-9Y6+rzw4p3jtEyBSiiErk13GFZTzwcDzqsQs12vDn9ovSTTn5Nyy6Csz7+O2t4SN
-qU4S/uLE6b/TiXj7196r58DcGvJgKbzbbnv/DUHGfaESrVWYLk3xoX3X8VJvP7jI
-M9XoZBbbgFLgAP5DFEvf5QWS9tR092z0YXOGr+mLHtkJM7Or9nKOohm6aFfHbuvu
-pSWyR4FWnaFANQ8wLH+fH485fiO6juJdTuRWeQpZddv0/IgguZ2Plu7z6NHCf5+L
-KYFjQ5y716wOufIqHhRLqYnpsAG2AFaMuPKzsy2KMifqoyB4KYR24EA1MCT7vwqu
-Hurp+SJrmNdkFVXbhGVUfMKf4nRZ37b9Miie0ju0OxJ9C3zY5uR5BMnqEjqq/rCX
-pQh5o1y+bWacOQVp0iQWJHfy8KkjhhQ1Pd1VeoVk9l2DsAJWm6unwMvGHviRcvzg
-BejDOVcE0x4xDj+TwAu2X2+w2hbUSY9W6lmkX4nGHlbLz211bIBFq42PzAMpRnYq
-jLxml4VpO4UnhyRp7Ipps99s7/iMFOn7AgMBAAEwDQYJKoZIhvcNAQELBQADggIB
-AG/5t56hKYKORne0bwJpMSCWZNT6JcYjf6fEmNrvG3/gz9BCuj4osZjJHD2OSUJl
-F5yI52RgPrXK8bNqJOvX6MIc4Y2JoSI2Uz4J2vZ3QhRkPC9oqwk/Enz4GIVJ4Dnm
-/kgpBbN2SN0TjnmEooptly5tWb3IPTjqLZpaPIW1ntQeCAbgrYVHiMsvNe1BuBrn
-RNi1xqw3QGp2ZV/RfJ3MH6d49TswEL1gwiUeg3hw5eG7IDfLB/2IJBrff7kmPTQ6
-n+il4uXuXMmX70xSvJXwP/NinomJsORZ4Npbmp7xV/QJp9cNoxNAo3DJ4OHRAnA+
-L7E1KZ3+nSRxGcVlqBekmG6wH9U39NN+dh758aGdJOWqA+B+1PAGxkvFCNqLgTpm
-xNl62YiRRo4FiIAkntvs+JneMEphv/T5i824t2xFZD2lBuW8r54nWj5cpx8AU9W2
-rulR0jx7BnVdj6czn1/pPCIah8Os9pZM8q1CbF8vXD+QLAF0/NjPNomTEGd/M+V+
-sfn1OhLGF/E1kWyNeOmkvX26txQdY8k6jUdsAc5vmQqgwxdorjI38ynpYQnFwq2g
-eO4l62sx8icsSh2TRklWy8BwZpaCyO/WVv/FcjIUexYhmZ0EHpmQk/RAlD1f9wFy
-CciNa/Dm94AwJgZk9LcXye3BSvb1sKF6C7eYrW0eI95V
------END CERTIFICATE-----
diff --git a/biometrics/fingerprint/aidl/default/Android.bp b/biometrics/fingerprint/aidl/default/Android.bp
index 3bb3f3a..a173a00 100644
--- a/biometrics/fingerprint/aidl/default/Android.bp
+++ b/biometrics/fingerprint/aidl/default/Android.bp
@@ -11,8 +11,6 @@
     name: "android.hardware.biometrics.fingerprint-service.example",
     vendor: true,
     relative_install_path: "hw",
-    init_rc: [":fingerprint-example.rc"],
-    vintf_fragments: [":fingerprint-example.xml"],
     local_include_dirs: ["include"],
     srcs: [
         "FakeLockoutTracker.cpp",
@@ -24,15 +22,21 @@
         "Session.cpp",
         "main.cpp",
     ],
+    stl: "c++_static",
     shared_libs: [
-        "libbase",
         "libbinder_ndk",
+        "liblog",
+    ],
+    static_libs: [
+        "libandroid.hardware.biometrics.fingerprint.VirtualProps",
+        "libbase",
         "android.hardware.biometrics.fingerprint-V3-ndk",
         "android.hardware.biometrics.common-V3-ndk",
         "android.hardware.biometrics.common.thread",
         "android.hardware.biometrics.common.util",
+        "android.hardware.keymaster-V4-ndk",
     ],
-    static_libs: ["libandroid.hardware.biometrics.fingerprint.VirtualProps"],
+    installable: false, // install APEX instead
 }
 
 cc_test {
@@ -143,12 +147,35 @@
     vendor: true,
 }
 
-filegroup {
+prebuilt_etc {
     name: "fingerprint-example.rc",
-    srcs: ["fingerprint-example.rc"],
+    src: "fingerprint-example.rc",
+    installable: false,
 }
 
-filegroup {
+prebuilt_etc {
     name: "fingerprint-example.xml",
-    srcs: ["fingerprint-example.xml"],
+    src: "fingerprint-example.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
+
+apex {
+    name: "com.android.hardware.biometrics.fingerprint.virtual",
+    manifest: "apex_manifest.json",
+    file_contexts: "apex_file_contexts",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
+    updatable: false,
+    vendor: true,
+
+    binaries: [
+        "android.hardware.biometrics.fingerprint-service.example",
+    ],
+    prebuilts: [
+        // init_rc
+        "fingerprint-example.rc",
+        // vintf_fragment
+        "fingerprint-example.xml",
+    ],
 }
diff --git a/biometrics/fingerprint/aidl/default/README.md b/biometrics/fingerprint/aidl/default/README.md
index 823cd18..4b4533a 100644
--- a/biometrics/fingerprint/aidl/default/README.md
+++ b/biometrics/fingerprint/aidl/default/README.md
@@ -11,12 +11,6 @@
 following to your device's `.mk` file to include it:
 
 ```
-PRODUCT_PACKAGES_DEBUG += android.hardware.biometrics.fingerprint-service.example
-```
-
-or add the following to include it as an apex:
-
-```
 PRODUCT_PACKAGES_DEBUG += com.android.hardware.biometrics.fingerprint.virtual
 ```
 
diff --git a/biometrics/fingerprint/aidl/default/apex/Android.bp b/biometrics/fingerprint/aidl/default/apex/Android.bp
deleted file mode 100644
index ad36ae2..0000000
--- a/biometrics/fingerprint/aidl/default/apex/Android.bp
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (C) 2023 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 {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
-    name: "com.android.hardware.biometrics.fingerprint.virtual.key",
-    public_key: "com.android.hardware.biometrics.fingerprint.virtual.avbpubkey",
-    private_key: "com.android.hardware.biometrics.fingerprint.virtual.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.biometrics.fingerprint.virtual.certificate",
-    certificate: "com.android.hardware.biometrics.fingerprint.virtual",
-}
-
-apex {
-    name: "com.android.hardware.biometrics.fingerprint.virtual",
-    manifest: "manifest.json",
-    file_contexts: "file_contexts",
-    key: "com.android.hardware.biometrics.fingerprint.virtual.key",
-    certificate: ":com.android.hardware.biometrics.fingerprint.virtual.certificate",
-    updatable: false,
-    use_vndk_as_stable: true,
-    vendor: true,
-
-    binaries: [
-        "android.hardware.biometrics.fingerprint-service.example",
-    ],
-    prebuilts: [
-        // init_rc
-        "fingerprint-example-apex.rc",
-        // vintf_fragment
-        "fingerprint-example-apex.xml",
-    ],
-
-    overrides: [
-        "android.hardware.biometrics.fingerprint-service.example",
-    ],
-}
-
-genrule {
-    name: "gen-fingerprint-example-apex.rc",
-    srcs: [":fingerprint-example.rc"],
-    out: ["fingerprint-example-apex.rc"],
-    cmd: "sed -e 's@/vendor/bin/@/apex/com.android.hardware.biometrics.fingerprint.virtual/bin/@' $(in) > $(out)",
-}
-
-prebuilt_etc {
-    name: "fingerprint-example-apex.rc",
-    src: ":gen-fingerprint-example-apex.rc",
-    installable: false,
-}
-
-prebuilt_etc {
-    name: "fingerprint-example-apex.xml",
-    src: ":fingerprint-example.xml",
-    sub_dir: "vintf",
-    installable: false,
-}
diff --git a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.avbpubkey b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.avbpubkey
deleted file mode 100644
index 9f2334a..0000000
--- a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pem b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pem
deleted file mode 100644
index 14eb288..0000000
--- a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-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
-qHAY4JU3ldxQzDUZCz5VCz372pgXkQ==
------END PRIVATE KEY-----
diff --git a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pk8 b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pk8
deleted file mode 100644
index ab59820..0000000
--- a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.pk8
+++ /dev/null
Binary files differ
diff --git a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.x509.pem b/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.x509.pem
deleted file mode 100644
index 6d10157..0000000
--- a/biometrics/fingerprint/aidl/default/apex/com.android.hardware.biometrics.fingerprint.virtual.x509.pem
+++ /dev/null
@@ -1,35 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGCzCCA/MCFFuIt0T1K9U92QfzZI3RpCyRp1ruMA0GCSqGSIb3DQEBCwUAMIHA
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTE8MDoGA1UEAwwzY29t
-LmFuZHJvaWQuaGFyZHdhcmUuYmlvbWV0cmljcy5maW5nZXJwcmludC52aXJ0dWFs
-MCAXDTIzMDUxMDA3MDkwMloYDzQ3NjEwNDA1MDcwOTAyWjCBwDELMAkGA1UEBhMC
-VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcx
-EDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNVBAsMB0FuZHJvaWQxIjAgBgkqhkiG9w0B
-CQEWE2FuZHJvaWRAYW5kcm9pZC5jb20xPDA6BgNVBAMMM2NvbS5hbmRyb2lkLmhh
-cmR3YXJlLmJpb21ldHJpY3MuZmluZ2VycHJpbnQudmlydHVhbDCCAiIwDQYJKoZI
-hvcNAQEBBQADggIPADCCAgoCggIBAMKXBcAw2Cs68KUMt5Hw2LVwkgEDiwqaXkG9
-V0SBK9y/q+6JCoxs9+4NsDPAEzHB+UHpqJ2i07VW1YV9F+2V93KCy/0fUjXIWmu8
-P0ixb+t8wlHZM2zYXQe9PELUZ/ZlYjAxkVKJjDmsCM8yzpRk+g3KKswlYwzyBoat
-qukrtvAaNKlRGJmjeStEo2o4qgQQUq96NAvSt3d6PsrNdFbXxqX61JT1dT8Kgxhk
-+oSAkV2/C2knQp/8ME1oJrK/D+glynXVqVkvYYplxp+GCIZUs/DOJcHyb+ZrNLJP
-f2zr4yDoB2pnV3G9VcjbdznWc661Wg+B2yZEvLVbOMiqaMRlpHzNczghowCy3xoq
-42IUmp3HLak0DUmrrUZDnJAAT/KEZxh/PwLeAcmUrQCbUiG5lN/njuZ5LjJ8gdcg
-v0RDPSIIszamrf2l+xlaI34iXS7xHf3OLTbgst2L7LhW5qmLsB1SZzAYGIUYnRWZ
-aqzaFIAWt28S0yhpOt+qS7b1l+fvMb09jiKfxzkYQh2bB0HrpbTl2x390q2GW6yE
-jmraC+nTiAVDCUnDjOVji7nXDloSmK+MDD/DaDQ47PoYE3hBqc0fsRr2aIlvMOvb
-m+4VhO85gCuJAK02XuixLPo6ZqBAEFNwQ4NDcuOHuODaaJ/amTxQBXRpNXUSnhXy
-ejpwspHrAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAGl3KGKMAWpefnRSQWs0n8kD
-eKYbzbe6mG0O5lqx5FKpJZpIki4RH1Yh5ZDR/NIeF2RNhlb/dqo99TKbCEGAoMB9
-R7EXDhyMcEXr5ATCA6iurhMKgkcLfOz6HkTI6k3wlPNuvx4iZGHD2KEvZiZGmae1
-dnK9iVtNs6ccyC0+V3y3Yt1fvjzp9SWcPpBXiO5QNf0sHxtzc32xXsBH0aLwLjDZ
-BCytwfEvq2S25v0r9m0fKquDBoFnk68cqClpNQZ9Ky0k8fGgOiQ5/jnVmgPmTheG
-mBcdPeUrhxGNs1vax/i/ysT4AVmDzIVW0uXVouhVeMQzykuy1+Ywa/Rn0jLxeNF2
-X3ooOE+EF8u9Pxf8ILRnfqok3VRuYLH6neNknTSKTx1aQAh9XbBpTUa/eCq3LDCP
-L6hSXYWjk9e5txbn0cNw9WuKMUg+Z9Qms3aVRFcvBxZQySEvf8FhgSrQbqbCbzhf
-dI0/ouW5w9iHUOh/FDvfETeZCeeTS+EOvGOqknzO8Y7PiChlgFsoMvC1GpHZ1ADy
-3xKSh15G92JCiv89CK2VvM8QDFh8ErQmSLjhMl700CLYis+AAZhCKOhAo573zj2u
-dZf29S+o3SEBhsl5snVGJW13Bu7BjxQtscCwKOv0g1cCkrqgcm2bMuNhpTK7rhMP
-i4hGSvbdGC27BtXbsiVX
------END CERTIFICATE-----
diff --git a/biometrics/fingerprint/aidl/default/apex/file_contexts b/biometrics/fingerprint/aidl/default/apex_file_contexts
similarity index 100%
rename from biometrics/fingerprint/aidl/default/apex/file_contexts
rename to biometrics/fingerprint/aidl/default/apex_file_contexts
diff --git a/biometrics/fingerprint/aidl/default/apex/manifest.json b/biometrics/fingerprint/aidl/default/apex_manifest.json
similarity index 100%
rename from biometrics/fingerprint/aidl/default/apex/manifest.json
rename to biometrics/fingerprint/aidl/default/apex_manifest.json
diff --git a/biometrics/fingerprint/aidl/default/fingerprint-example.rc b/biometrics/fingerprint/aidl/default/fingerprint-example.rc
index ee4713c..da4ea45 100644
--- a/biometrics/fingerprint/aidl/default/fingerprint-example.rc
+++ b/biometrics/fingerprint/aidl/default/fingerprint-example.rc
@@ -1,4 +1,4 @@
-service vendor.fingerprint-example /vendor/bin/hw/android.hardware.biometrics.fingerprint-service.example
+service vendor.fingerprint-example /apex/com.android.hardware.biometrics.fingerprint.virtual/bin/hw/android.hardware.biometrics.fingerprint-service.example
     class hal
     user nobody
     group nobody
diff --git a/boot/1.1/default/Android.bp b/boot/1.1/default/Android.bp
index 0b0a5b7..e7a8d6e 100644
--- a/boot/1.1/default/Android.bp
+++ b/boot/1.1/default/Android.bp
@@ -20,6 +20,7 @@
     srcs: ["BootControl.cpp"],
 
     shared_libs: [
+        "libbase",
         "liblog",
         "libhidlbase",
         "libhardware",
diff --git a/boot/1.1/default/boot_control/Android.bp b/boot/1.1/default/boot_control/Android.bp
index 6aa30c2..d0dcb59 100644
--- a/boot/1.1/default/boot_control/Android.bp
+++ b/boot/1.1/default/boot_control/Android.bp
@@ -35,14 +35,13 @@
     ],
 
     shared_libs: [
-        "android.hardware.boot@1.1",
-        "libbase",
         "liblog",
     ],
     static_libs: [
         "libbootloader_message",
         "libfstab",
     ],
+
 }
 
 cc_library_static {
@@ -52,7 +51,13 @@
     recovery_available: true,
     vendor_available: true,
 
-    srcs: ["libboot_control.cpp"],
+    srcs: [
+        "libboot_control.cpp",
+    ],
+    static_libs: [
+        "android.hardware.boot@1.1",
+        "libbase",
+    ],
 }
 
 cc_library_shared {
@@ -67,6 +72,8 @@
         "libboot_control",
     ],
     shared_libs: [
+        "android.hardware.boot@1.1",
+        "libbase",
         "libhardware",
     ],
 }
diff --git a/boot/1.2/default/Android.bp b/boot/1.2/default/Android.bp
index 4e1c35e..f1e9c34 100644
--- a/boot/1.2/default/Android.bp
+++ b/boot/1.2/default/Android.bp
@@ -20,6 +20,7 @@
     srcs: ["BootControl.cpp"],
 
     shared_libs: [
+        "libbase",
         "liblog",
         "libhidlbase",
         "libhardware",
diff --git a/boot/aidl/default/Android.bp b/boot/aidl/default/Android.bp
index dcb40db..c1d3c57 100644
--- a/boot/aidl/default/Android.bp
+++ b/boot/aidl/default/Android.bp
@@ -27,7 +27,39 @@
     name: "android.hardware.boot-service_common",
     relative_install_path: "hw",
     defaults: ["libboot_control_defaults"],
+    srcs: [
+        "main.cpp",
+        "BootControl.cpp",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.boot-service.default",
+    defaults: ["android.hardware.boot-service_common"],
+    vendor: true,
+
+    stl: "c++_static",
+    shared_libs: [
+        "libbinder_ndk",
+        "liblog",
+    ],
+    static_libs: [
+        "android.hardware.boot@1.1",
+        "android.hardware.boot-V1-ndk",
+        "libbase",
+        "libboot_control",
+    ],
+
+    installable: false, // installed in APEX
+}
+
+cc_binary {
+    name: "android.hardware.boot-service.default_recovery",
+    defaults: ["android.hardware.boot-service_common"],
+    init_rc: ["android.hardware.boot-service.default_recovery.rc"],
     vintf_fragments: ["android.hardware.boot-service.default.xml"],
+    recovery: true,
+
     shared_libs: [
         "libbase",
         "libbinder_ndk",
@@ -37,19 +69,35 @@
     static_libs: [
         "libboot_control",
     ],
-    srcs: ["main.cpp", "BootControl.cpp"],
 }
 
-cc_binary {
-    name: "android.hardware.boot-service.default",
-    defaults: ["android.hardware.boot-service_common"],
-    init_rc: ["android.hardware.boot-service.default.rc"],
+prebuilt_etc {
+    name: "android.hardware.boot-service.default.rc",
+    src: "android.hardware.boot-service.default.rc",
+    installable: false,
+}
+
+prebuilt_etc {
+    name: "android.hardware.boot-service.default.xml",
+    src: "android.hardware.boot-service.default.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
+
+apex {
+    name: "com.android.hardware.boot",
     vendor: true,
-}
+    manifest: "apex_manifest.json",
+    file_contexts: "apex_file_contexts",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
+    updatable: false,
 
-cc_binary {
-    name: "android.hardware.boot-service.default_recovery",
-    defaults: ["android.hardware.boot-service_common"],
-    init_rc: ["android.hardware.boot-service.default_recovery.rc"],
-    recovery: true,
+    binaries: [
+        "android.hardware.boot-service.default",
+    ],
+    prebuilts: [
+        "android.hardware.boot-service.default.rc",
+        "android.hardware.boot-service.default.xml",
+    ],
 }
diff --git a/boot/aidl/default/android.hardware.boot-service.default.rc b/boot/aidl/default/android.hardware.boot-service.default.rc
index 589f803..5090e2c 100644
--- a/boot/aidl/default/android.hardware.boot-service.default.rc
+++ b/boot/aidl/default/android.hardware.boot-service.default.rc
@@ -1,4 +1,4 @@
-service vendor.boot-default /vendor/bin/hw/android.hardware.boot-service.default
+service vendor.boot-default /apex/com.android.hardware.boot/bin/hw/android.hardware.boot-service.default
     class early_hal
     user root
     group root
diff --git a/boot/aidl/default/apex_file_contexts b/boot/aidl/default/apex_file_contexts
new file mode 100644
index 0000000..bf03585
--- /dev/null
+++ b/boot/aidl/default/apex_file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                                          u:object_r:vendor_file:s0
+/etc(/.*)?                                                      u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.boot-service\.default                u:object_r:hal_bootctl_default_exec:s0
diff --git a/boot/aidl/default/apex_manifest.json b/boot/aidl/default/apex_manifest.json
new file mode 100644
index 0000000..92661c9
--- /dev/null
+++ b/boot/aidl/default/apex_manifest.json
@@ -0,0 +1,5 @@
+{
+    "name": "com.android.hardware.boot",
+    "version": 1,
+    "vendorBootstrap": true
+}
\ No newline at end of file
diff --git a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
index 356673f..790d60b 100644
--- a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
+++ b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
@@ -32,11 +32,11 @@
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
 #include <broadcastradio-utils-aidl/Utils.h>
-#include <broadcastradio-vts-utils/mock-timeout.h>
 #include <cutils/bitops.h>
 #include <gmock/gmock.h>
 
 #include <chrono>
+#include <condition_variable>
 #include <optional>
 #include <regex>
 
@@ -61,11 +61,6 @@
 
 namespace bcutils = ::aidl::android::hardware::broadcastradio::utils;
 
-inline constexpr std::chrono::seconds kTuneTimeoutSec =
-        std::chrono::seconds(IBroadcastRadio::TUNER_TIMEOUT_MS * 1000);
-inline constexpr std::chrono::seconds kProgramListScanTimeoutSec =
-        std::chrono::seconds(IBroadcastRadio::LIST_COMPLETE_TIMEOUT_MS * 1000);
-
 const ConfigFlag kConfigFlagValues[] = {
         ConfigFlag::FORCE_MONO,
         ConfigFlag::FORCE_ANALOG,
@@ -108,20 +103,68 @@
 
 }  // namespace
 
-class TunerCallbackMock : public BnTunerCallback {
+class CallbackFlag final {
   public:
-    TunerCallbackMock();
+    CallbackFlag(int timeoutMs) { mTimeoutMs = timeoutMs; }
+    /**
+     * Notify that the callback is called.
+     */
+    void notify() {
+        std::unique_lock<std::mutex> lock(mMutex);
+        mCalled = true;
+        lock.unlock();
+        mCv.notify_all();
+    };
+
+    /**
+     * Wait for the timeout passed into the constructor.
+     */
+    bool wait() {
+        std::unique_lock<std::mutex> lock(mMutex);
+        return mCv.wait_for(lock, std::chrono::milliseconds(mTimeoutMs),
+                            [this] { return mCalled; });
+    };
+
+    /**
+     * Reset the callback to not called.
+     */
+    void reset() {
+        std::unique_lock<std::mutex> lock(mMutex);
+        mCalled = false;
+    }
+
+  private:
+    std::mutex mMutex;
+    bool mCalled GUARDED_BY(mMutex) = false;
+    std::condition_variable mCv;
+    int mTimeoutMs;
+};
+
+class TunerCallbackImpl final : public BnTunerCallback {
+  public:
+    TunerCallbackImpl();
     ScopedAStatus onTuneFailed(Result result, const ProgramSelector& selector) override;
-    MOCK_TIMEOUT_METHOD1(onCurrentProgramInfoChangedMock, ScopedAStatus(const ProgramInfo&));
     ScopedAStatus onCurrentProgramInfoChanged(const ProgramInfo& info) override;
     ScopedAStatus onProgramListUpdated(const ProgramListChunk& chunk) override;
-    MOCK_METHOD1(onAntennaStateChange, ScopedAStatus(bool connected));
-    MOCK_METHOD1(onParametersUpdated, ScopedAStatus(const vector<VendorKeyValue>& parameters));
-    MOCK_METHOD2(onConfigFlagUpdated, ScopedAStatus(ConfigFlag in_flag, bool in_value));
-    MOCK_TIMEOUT_METHOD0(onProgramListReady, void());
+    ScopedAStatus onParametersUpdated(const vector<VendorKeyValue>& parameters) override;
+    ScopedAStatus onAntennaStateChange(bool connected) override;
+    ScopedAStatus onConfigFlagUpdated(ConfigFlag in_flag, bool in_value) override;
 
+    bool waitOnCurrentProgramInfoChangedCallback();
+    bool waitProgramReady();
+    void reset();
+
+    bool getAntennaConnectionState();
+    ProgramInfo getCurrentProgramInfo();
+    bcutils::ProgramInfoSet getProgramList();
+
+  private:
     std::mutex mLock;
+    bool mAntennaConnectionState GUARDED_BY(mLock);
+    ProgramInfo mCurrentProgramInfo GUARDED_BY(mLock);
     bcutils::ProgramInfoSet mProgramList GUARDED_BY(mLock);
+    CallbackFlag mOnCurrentProgramInfoChangedFlag = CallbackFlag(IBroadcastRadio::TUNER_TIMEOUT_MS);
+    CallbackFlag mOnProgramListReadyFlag = CallbackFlag(IBroadcastRadio::LIST_COMPLETE_TIMEOUT_MS);
 };
 
 struct AnnouncementListenerMock : public BnAnnouncementListener {
@@ -139,7 +182,7 @@
 
     std::shared_ptr<IBroadcastRadio> mModule;
     Properties mProperties;
-    std::shared_ptr<TunerCallbackMock> mCallback = SharedRefBase::make<TunerCallbackMock>();
+    std::shared_ptr<TunerCallbackImpl> mCallback;
 };
 
 MATCHER_P(InfoHasId, id, string(negation ? "does not contain" : "contains") + " " + id.toString()) {
@@ -147,20 +190,18 @@
     return ids.end() != find(ids.begin(), ids.end(), id.value);
 }
 
-TunerCallbackMock::TunerCallbackMock() {
-    EXPECT_TIMEOUT_CALL(*this, onCurrentProgramInfoChangedMock, _).Times(AnyNumber());
-
-    // we expect the antenna is connected through the whole test
-    EXPECT_CALL(*this, onAntennaStateChange(false)).Times(0);
+TunerCallbackImpl::TunerCallbackImpl() {
+    mAntennaConnectionState = true;
 }
 
-ScopedAStatus TunerCallbackMock::onTuneFailed(Result result, const ProgramSelector& selector) {
+ScopedAStatus TunerCallbackImpl::onTuneFailed(Result result, const ProgramSelector& selector) {
     LOG(DEBUG) << "Tune failed for selector" << selector.toString();
     EXPECT_TRUE(result == Result::CANCELED);
     return ndk::ScopedAStatus::ok();
 }
 
-ScopedAStatus TunerCallbackMock::onCurrentProgramInfoChanged(const ProgramInfo& info) {
+ScopedAStatus TunerCallbackImpl::onCurrentProgramInfoChanged(const ProgramInfo& info) {
+    LOG(DEBUG) << "onCurrentProgramInfoChanged called";
     for (const auto& id : info.selector) {
         EXPECT_NE(id.type, IdentifierType::INVALID);
     }
@@ -196,21 +237,75 @@
         }
     }
 
-    return onCurrentProgramInfoChangedMock(info);
+    {
+        std::lock_guard<std::mutex> lk(mLock);
+        mCurrentProgramInfo = info;
+    }
+
+    mOnCurrentProgramInfoChangedFlag.notify();
+    return ndk::ScopedAStatus::ok();
 }
 
-ScopedAStatus TunerCallbackMock::onProgramListUpdated(const ProgramListChunk& chunk) {
-    std::lock_guard<std::mutex> lk(mLock);
-
-    updateProgramList(chunk, &mProgramList);
+ScopedAStatus TunerCallbackImpl::onProgramListUpdated(const ProgramListChunk& chunk) {
+    LOG(DEBUG) << "onProgramListUpdated called";
+    {
+        std::lock_guard<std::mutex> lk(mLock);
+        updateProgramList(chunk, &mProgramList);
+    }
 
     if (chunk.complete) {
-        onProgramListReady();
+        mOnProgramListReadyFlag.notify();
     }
 
     return ndk::ScopedAStatus::ok();
 }
 
+ScopedAStatus TunerCallbackImpl::onParametersUpdated(
+        [[maybe_unused]] const vector<VendorKeyValue>& parameters) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ScopedAStatus TunerCallbackImpl::onAntennaStateChange(bool connected) {
+    if (!connected) {
+        std::lock_guard<std::mutex> lk(mLock);
+        mAntennaConnectionState = false;
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ScopedAStatus TunerCallbackImpl::onConfigFlagUpdated([[maybe_unused]] ConfigFlag in_flag,
+                                                     [[maybe_unused]] bool in_value) {
+    return ndk::ScopedAStatus::ok();
+}
+
+bool TunerCallbackImpl::waitOnCurrentProgramInfoChangedCallback() {
+    return mOnCurrentProgramInfoChangedFlag.wait();
+}
+
+bool TunerCallbackImpl::waitProgramReady() {
+    return mOnProgramListReadyFlag.wait();
+}
+
+void TunerCallbackImpl::reset() {
+    mOnCurrentProgramInfoChangedFlag.reset();
+    mOnProgramListReadyFlag.reset();
+}
+
+bool TunerCallbackImpl::getAntennaConnectionState() {
+    std::lock_guard<std::mutex> lk(mLock);
+    return mAntennaConnectionState;
+}
+
+ProgramInfo TunerCallbackImpl::getCurrentProgramInfo() {
+    std::lock_guard<std::mutex> lk(mLock);
+    return mCurrentProgramInfo;
+}
+
+bcutils::ProgramInfoSet TunerCallbackImpl::getProgramList() {
+    std::lock_guard<std::mutex> lk(mLock);
+    return mProgramList;
+}
+
 void BroadcastRadioHalTest::SetUp() {
     EXPECT_EQ(mModule.get(), nullptr) << "Module is already open";
 
@@ -228,6 +323,8 @@
     EXPECT_FALSE(mProperties.product.empty());
     EXPECT_GT(mProperties.supportedIdentifierTypes.size(), 0u);
 
+    mCallback = SharedRefBase::make<TunerCallbackImpl>();
+
     // set callback
     EXPECT_TRUE(mModule->setTunerCallback(mCallback).isOk());
 }
@@ -236,6 +333,11 @@
     if (mModule) {
         ASSERT_TRUE(mModule->unsetTunerCallback().isOk());
     }
+    if (mCallback) {
+        // we expect the antenna is connected through the whole test
+        EXPECT_TRUE(mCallback->getAntennaConnectionState());
+        mCallback = nullptr;
+    }
 }
 
 bool BroadcastRadioHalTest::getAmFmRegionConfig(bool full, AmFmRegionConfig* config) {
@@ -256,7 +358,7 @@
 
 std::optional<bcutils::ProgramInfoSet> BroadcastRadioHalTest::getProgramList(
         const ProgramFilter& filter) {
-    EXPECT_TIMEOUT_CALL(*mCallback, onProgramListReady).Times(AnyNumber());
+    mCallback->reset();
 
     auto startResult = mModule->startProgramListUpdates(filter);
 
@@ -268,13 +370,13 @@
     if (!startResult.isOk()) {
         return std::nullopt;
     }
-    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onProgramListReady, kProgramListScanTimeoutSec);
+    EXPECT_TRUE(mCallback->waitProgramReady());
 
     auto stopResult = mModule->stopProgramListUpdates();
 
     EXPECT_TRUE(stopResult.isOk());
 
-    return mCallback->mProgramList;
+    return mCallback->getProgramList();
 }
 
 /**
@@ -456,7 +558,7 @@
  *  - if it is supported, the test is ignored;
  */
 TEST_P(BroadcastRadioHalTest, TuneFailsWithNotSupported) {
-    LOG(DEBUG) << "TuneFailsWithInvalid Test";
+    LOG(DEBUG) << "TuneFailsWithNotSupported Test";
 
     vector<ProgramIdentifier> supportTestId = {
             makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, 0),           // invalid
@@ -477,9 +579,9 @@
     for (const auto& id : supportTestId) {
         ProgramSelector sel{id, {}};
 
-        auto result = mModule->tune(sel);
-
         if (!bcutils::isSupported(mProperties, sel)) {
+            auto result = mModule->tune(sel);
+
             EXPECT_EQ(result.getServiceSpecificError(), notSupportedError);
         }
     }
@@ -508,9 +610,9 @@
     for (const auto& id : invalidId) {
         ProgramSelector sel{id, {}};
 
-        auto result = mModule->tune(sel);
-
         if (bcutils::isSupported(mProperties, sel)) {
+            auto result = mModule->tune(sel);
+
             EXPECT_EQ(result.getServiceSpecificError(), invalidArgumentsError);
         }
     }
@@ -549,13 +651,7 @@
     int64_t freq = 90900;  // 90.9 FM
     ProgramSelector sel = makeSelectorAmfm(freq);
     // try tuning
-    ProgramInfo infoCb = {};
-    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChangedMock,
-                        InfoHasId(makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, freq)))
-            .Times(AnyNumber())
-            .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(ndk::ScopedAStatus::ok()))))
-            .WillRepeatedly(testing::InvokeWithoutArgs([] { return ndk::ScopedAStatus::ok(); }));
-
+    mCallback->reset();
     auto result = mModule->tune(sel);
 
     // expect a failure if it's not supported
@@ -566,7 +662,8 @@
 
     // expect a callback if it succeeds
     EXPECT_TRUE(result.isOk());
-    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChangedMock, kTuneTimeoutSec);
+    EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback());
+    ProgramInfo infoCb = mCallback->getCurrentProgramInfo();
 
     LOG(DEBUG) << "Current program info: " << infoCb.toString();
 
@@ -638,12 +735,6 @@
     }
 
     // try tuning
-    ProgramInfo infoCb = {};
-    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChangedMock,
-                        InfoHasId(makeIdentifier(IdentifierType::DAB_FREQUENCY_KHZ, freq)))
-            .Times(AnyNumber())
-            .WillOnce(
-                    DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(ndk::ScopedAStatus::ok()))));
 
     auto result = mModule->tune(sel);
 
@@ -655,7 +746,9 @@
 
     // expect a callback if it succeeds
     EXPECT_TRUE(result.isOk());
-    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChangedMock, kTuneTimeoutSec);
+    EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback());
+    ProgramInfo infoCb = mCallback->getCurrentProgramInfo();
+
     LOG(DEBUG) << "Current program info: " << infoCb.toString();
 
     // it should tune exactly to what was requested
@@ -669,13 +762,13 @@
  *
  * Verifies that:
  *  - the method succeeds;
- *  - the program info is changed within kTuneTimeoutSec;
+ *  - the program info is changed within kTuneTimeoutMs;
  *  - works both directions and with or without skipping sub-channel.
  */
 TEST_P(BroadcastRadioHalTest, Seek) {
     LOG(DEBUG) << "Seek Test";
 
-    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChangedMock, _).Times(AnyNumber());
+    mCallback->reset();
 
     auto result = mModule->seek(/* in_directionUp= */ true, /* in_skipSubChannel= */ true);
 
@@ -685,14 +778,14 @@
     }
 
     EXPECT_TRUE(result.isOk());
-    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChangedMock, kTuneTimeoutSec);
+    EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback());
 
-    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChangedMock, _).Times(AnyNumber());
+    mCallback->reset();
 
     result = mModule->seek(/* in_directionUp= */ false, /* in_skipSubChannel= */ false);
 
     EXPECT_TRUE(result.isOk());
-    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChangedMock, kTuneTimeoutSec);
+    EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback());
 }
 
 /**
@@ -720,13 +813,13 @@
  *
  * Verifies that:
  *  - the method succeeds or returns NOT_SUPPORTED;
- *  - the program info is changed within kTuneTimeoutSec if the method succeeded;
+ *  - the program info is changed within kTuneTimeoutMs if the method succeeded;
  *  - works both directions.
  */
 TEST_P(BroadcastRadioHalTest, Step) {
     LOG(DEBUG) << "Step Test";
 
-    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChangedMock, _).Times(AnyNumber());
+    mCallback->reset();
 
     auto result = mModule->step(/* in_directionUp= */ true);
 
@@ -735,14 +828,14 @@
         return;
     }
     EXPECT_TRUE(result.isOk());
-    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChangedMock, kTuneTimeoutSec);
+    EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback());
 
-    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChangedMock, _).Times(AnyNumber());
+    mCallback->reset();
 
     result = mModule->step(/* in_directionUp= */ false);
 
     EXPECT_TRUE(result.isOk());
-    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChangedMock, kTuneTimeoutSec);
+    EXPECT_TRUE(mCallback->waitOnCurrentProgramInfoChangedCallback());
 }
 
 /**
@@ -904,13 +997,12 @@
     LOG(DEBUG) << "SetConfigFlags Test";
 
     auto get = [&](ConfigFlag flag) -> bool {
-        bool* gotValue = nullptr;
+        bool gotValue;
 
-        auto halResult = mModule->isConfigFlagSet(flag, gotValue);
+        auto halResult = mModule->isConfigFlagSet(flag, &gotValue);
 
-        EXPECT_FALSE(gotValue == nullptr);
         EXPECT_TRUE(halResult.isOk());
-        return *gotValue;
+        return gotValue;
     };
 
     auto notSupportedError = resultToInt(Result::NOT_SUPPORTED);
@@ -955,7 +1047,7 @@
  *
  * Verifies that:
  * - startProgramListUpdates either succeeds or returns NOT_SUPPORTED;
- * - the complete list is fetched within kProgramListScanTimeoutSec;
+ * - the complete list is fetched within kProgramListScanTimeoutMs;
  * - stopProgramListUpdates does not crash.
  */
 TEST_P(BroadcastRadioHalTest, GetProgramListFromEmptyFilter) {
@@ -969,7 +1061,7 @@
  *
  * Verifies that:
  * - startProgramListUpdates either succeeds or returns NOT_SUPPORTED;
- * - the complete list is fetched within kProgramListScanTimeoutSec;
+ * - the complete list is fetched within kProgramListScanTimeoutMs;
  * - stopProgramListUpdates does not crash;
  * - result for startProgramListUpdates using a filter with AMFM_FREQUENCY_KHZ value of the first
  *   AMFM program matches the expected result.
@@ -1017,7 +1109,7 @@
  *
  * Verifies that:
  * - startProgramListUpdates either succeeds or returns NOT_SUPPORTED;
- * - the complete list is fetched within kProgramListScanTimeoutSec;
+ * - the complete list is fetched within kProgramListScanTimeoutMs;
  * - stopProgramListUpdates does not crash;
  * - result for startProgramListUpdates using a filter with DAB_ENSEMBLE value of the first DAB
  *   program matches the expected result.
diff --git a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
index be69632..b6b5206 100644
--- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
+++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
@@ -552,6 +552,11 @@
             stream.rotation = StreamRotation::ROTATION_0;
             stream.dynamicRangeProfile = RequestAvailableDynamicRangeProfilesMap::
                     ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
+            stream.useCase = ScalerAvailableStreamUseCases::
+                    ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
+            stream.colorSpace = static_cast<int>(
+                    RequestAvailableColorSpaceProfilesMap::
+                            ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED);
 
             std::vector<Stream> streams = {stream};
             StreamConfiguration config;
diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp
index ce1cbfd..6a17453 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -45,8 +45,6 @@
 using ::aidl::android::hardware::camera::device::CameraMetadata;
 using ::aidl::android::hardware::camera::device::ICameraDevice;
 using ::aidl::android::hardware::camera::metadata::CameraMetadataTag;
-using ::aidl::android::hardware::camera::metadata::RequestAvailableColorSpaceProfilesMap;
-using ::aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
 using ::aidl::android::hardware::camera::metadata::SensorInfoColorFilterArrangement;
 using ::aidl::android::hardware::camera::metadata::SensorPixelMode;
 using ::aidl::android::hardware::camera::provider::BnCameraProviderCallback;
@@ -122,7 +120,7 @@
     ABinderProcess_startThreadPool();
 
     SpAIBinder cameraProviderBinder =
-            SpAIBinder(AServiceManager_getService(serviceDescriptor.c_str()));
+            SpAIBinder(AServiceManager_waitForService(serviceDescriptor.c_str()));
     ASSERT_NE(cameraProviderBinder.get(), nullptr);
 
     std::shared_ptr<ICameraProvider> cameraProvider =
@@ -2321,21 +2319,26 @@
         }
 
         std::vector<Stream> streams(1);
-        streams[0] = {0,
-                      StreamType::OUTPUT,
-                      outputPreviewStreams[0].width,
-                      outputPreviewStreams[0].height,
-                      static_cast<PixelFormat>(outputPreviewStreams[0].format),
-                      static_cast<::aidl::android::hardware::graphics::common::BufferUsage>(
-                              GRALLOC1_CONSUMER_USAGE_CPU_READ),
-                      Dataspace::UNKNOWN,
-                      StreamRotation::ROTATION_0,
-                      std::string(),
-                      0,
-                      -1,
-                      {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
-                      RequestAvailableDynamicRangeProfilesMap::
-                              ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
+        streams[0] = {
+                0,
+                StreamType::OUTPUT,
+                outputPreviewStreams[0].width,
+                outputPreviewStreams[0].height,
+                static_cast<PixelFormat>(outputPreviewStreams[0].format),
+                static_cast<::aidl::android::hardware::graphics::common::BufferUsage>(
+                        GRALLOC1_CONSUMER_USAGE_CPU_READ),
+                Dataspace::UNKNOWN,
+                StreamRotation::ROTATION_0,
+                std::string(),
+                0,
+                -1,
+                {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
+                RequestAvailableDynamicRangeProfilesMap::
+                        ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
+                ScalerAvailableStreamUseCases::ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+                static_cast<int>(
+                        RequestAvailableColorSpaceProfilesMap::
+                                ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED)};
 
         int32_t streamConfigCounter = 0;
         CameraMetadata req;
@@ -2479,7 +2482,11 @@
                   /*groupId*/ -1,
                   {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
                   RequestAvailableDynamicRangeProfilesMap::
-                          ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
+                          ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
+                  ScalerAvailableStreamUseCases::ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+                  static_cast<int>(
+                          RequestAvailableColorSpaceProfilesMap::
+                                  ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED)};
 
     StreamConfiguration config;
     config.streams = streams;
@@ -2810,21 +2817,26 @@
     std::vector<Stream> streams(physicalIds.size());
     int32_t streamId = 0;
     for (auto const& physicalId : physicalIds) {
-        streams[streamId] = {streamId,
-                             StreamType::OUTPUT,
-                             outputPreviewStreams[0].width,
-                             outputPreviewStreams[0].height,
-                             static_cast<PixelFormat>(outputPreviewStreams[0].format),
-                             static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
-                                     GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
-                             Dataspace::UNKNOWN,
-                             StreamRotation::ROTATION_0,
-                             physicalId,
-                             0,
-                             -1,
-                             {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
-                             RequestAvailableDynamicRangeProfilesMap::
-                                     ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
+        streams[streamId] = {
+                streamId,
+                StreamType::OUTPUT,
+                outputPreviewStreams[0].width,
+                outputPreviewStreams[0].height,
+                static_cast<PixelFormat>(outputPreviewStreams[0].format),
+                static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
+                        GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
+                Dataspace::UNKNOWN,
+                StreamRotation::ROTATION_0,
+                physicalId,
+                0,
+                -1,
+                {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
+                RequestAvailableDynamicRangeProfilesMap::
+                        ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
+                ScalerAvailableStreamUseCases::ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+                static_cast<int>(
+                        RequestAvailableColorSpaceProfilesMap::
+                                ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED)};
         streamId++;
     }
 
@@ -2883,7 +2895,8 @@
                                       bool* supportsPartialResults, int32_t* partialResultCount,
                                       bool* useHalBufManager, std::shared_ptr<DeviceCb>* outCb,
                                       uint32_t streamConfigCounter, bool maxResolution,
-                                      RequestAvailableDynamicRangeProfilesMap prof) {
+                                      RequestAvailableDynamicRangeProfilesMap dynamicRangeProf,
+                                      RequestAvailableColorSpaceProfilesMap colorSpaceProf) {
     ASSERT_NE(nullptr, session);
     ASSERT_NE(nullptr, halStreams);
     ASSERT_NE(nullptr, previewStream);
@@ -2965,7 +2978,9 @@
                   -1,
                   {maxResolution ? SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION
                                  : SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
-                  prof};
+                  dynamicRangeProf,
+                  ScalerAvailableStreamUseCases::ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+                  static_cast<int>(colorSpaceProf)};
 
     StreamConfiguration config;
     config.streams = streams;
@@ -3416,7 +3431,11 @@
                   /*groupId*/ 0,
                   {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
                   RequestAvailableDynamicRangeProfilesMap::
-                          ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
+                          ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
+                  ScalerAvailableStreamUseCases::ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+                  static_cast<int>(
+                          RequestAvailableColorSpaceProfilesMap::
+                                  ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED)};
 
     StreamConfiguration config = {streams, StreamConfigurationMode::NORMAL_MODE, CameraMetadata()};
 
@@ -3531,15 +3550,12 @@
         Stream previewStream;
         std::shared_ptr<DeviceCb> cb;
 
-        previewStream.usage =
-            static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
-                    GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
-        previewStream.dataSpace = getDataspace(PixelFormat::IMPLEMENTATION_DEFINED);
-        previewStream.colorSpace = static_cast<int32_t>(colorSpace);
+        previewStream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
+                GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
         configureStreams(name, mProvider, PixelFormat::IMPLEMENTATION_DEFINED, &mSession,
-                            &previewStream, &halStreams, &supportsPartialResults,
-                            &partialResultCount, &useHalBufManager, &cb, 0,
-                            /*maxResolution*/ false, dynamicRangeProfile);
+                         &previewStream, &halStreams, &supportsPartialResults, &partialResultCount,
+                         &useHalBufManager, &cb, 0,
+                         /*maxResolution*/ false, dynamicRangeProfile, colorSpace);
         ASSERT_NE(mSession, nullptr);
 
         ::aidl::android::hardware::common::fmq::MQDescriptor<
diff --git a/camera/provider/aidl/vts/camera_aidl_test.h b/camera/provider/aidl/vts/camera_aidl_test.h
index 809af0a..3018d5a 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.h
+++ b/camera/provider/aidl/vts/camera_aidl_test.h
@@ -77,6 +77,9 @@
 using ::aidl::android::hardware::camera::device::StreamBufferRet;
 using ::aidl::android::hardware::camera::device::StreamConfiguration;
 using ::aidl::android::hardware::camera::device::StreamConfigurationMode;
+using ::aidl::android::hardware::camera::metadata::RequestAvailableColorSpaceProfilesMap;
+using ::aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
+using ::aidl::android::hardware::camera::metadata::ScalerAvailableStreamUseCases;
 using ::aidl::android::hardware::camera::provider::ConcurrentCameraIdCombination;
 using ::aidl::android::hardware::camera::provider::ICameraProvider;
 
@@ -205,10 +208,12 @@
             bool* supportsPartialResults /*out*/, int32_t* partialResultCount /*out*/,
             bool* useHalBufManager /*out*/, std::shared_ptr<DeviceCb>* outCb /*out*/,
             uint32_t streamConfigCounter, bool maxResolution,
-            aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap
-                    prof = ::aidl::android::hardware::camera::metadata::
-                            RequestAvailableDynamicRangeProfilesMap::
-                                    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
+            RequestAvailableDynamicRangeProfilesMap dynamicRangeProf =
+                    RequestAvailableDynamicRangeProfilesMap::
+                            ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
+            RequestAvailableColorSpaceProfilesMap colorSpaceProf =
+                    RequestAvailableColorSpaceProfilesMap::
+                            ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED);
 
     void configurePreviewStreams(
             const std::string& name, const std::shared_ptr<ICameraProvider>& provider,
@@ -379,8 +384,7 @@
 
     static void get10BitDynamicRangeProfiles(
             const camera_metadata_t* staticMeta,
-            std::vector<aidl::android::hardware::camera::metadata::
-                                RequestAvailableDynamicRangeProfilesMap>* profiles);
+            std::vector<RequestAvailableDynamicRangeProfilesMap>* profiles);
 
     static bool reportsColorSpaces(const camera_metadata_t* staticMeta);
 
@@ -390,17 +394,13 @@
                                 RequestAvailableColorSpaceProfilesMap>* profiles);
 
     static bool isColorSpaceCompatibleWithDynamicRangeAndPixelFormat(
-            const camera_metadata_t* staticMeta,
-            aidl::android::hardware::camera::metadata::
-            RequestAvailableColorSpaceProfilesMap colorSpace,
-            aidl::android::hardware::camera::metadata::
+            const camera_metadata_t* staticMeta, RequestAvailableColorSpaceProfilesMap colorSpace,
             RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile,
             aidl::android::hardware::graphics::common::PixelFormat pixelFormat);
 
-    static const char* getColorSpaceProfileString(aidl::android::hardware::camera::metadata::
-            RequestAvailableColorSpaceProfilesMap colorSpace);
+    static const char* getColorSpaceProfileString(RequestAvailableColorSpaceProfilesMap colorSpace);
 
-    static const char* getDynamicRangeProfileString(aidl::android::hardware::camera::metadata::
+    static const char* getDynamicRangeProfileString(
             RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile);
 
     static int32_t halFormatToPublicFormat(
@@ -411,10 +411,8 @@
 
     static Size getMinSize(Size a, Size b);
 
-    void processColorSpaceRequest(aidl::android::hardware::camera::metadata::
-            RequestAvailableColorSpaceProfilesMap colorSpace,
-            aidl::android::hardware::camera::metadata::
-            RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile);
+    void processColorSpaceRequest(RequestAvailableColorSpaceProfilesMap colorSpace,
+                                  RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile);
 
     void processZoomSettingsOverrideRequests(
             int32_t frameCount, const bool *overrideSequence, const bool *expectedResults);
@@ -574,10 +572,8 @@
     static bool matchDeviceName(const std::string& deviceName, const std::string& providerType,
                                 std::string* deviceVersion, std::string* cameraId);
 
-    static void verify10BitMetadata(
-            HandleImporter& importer, const InFlightRequest& request,
-            aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap
-                    profile);
+    static void verify10BitMetadata(HandleImporter& importer, const InFlightRequest& request,
+                                    RequestAvailableDynamicRangeProfilesMap profile);
 
     static void waitForReleaseFence(
             std::vector<InFlightRequest::StreamBufferAndTimestamp>& resultOutputBuffers);
diff --git a/cas/aidl/default/Android.bp b/cas/aidl/default/Android.bp
index 9d094e0..06e167c 100644
--- a/cas/aidl/default/Android.bp
+++ b/cas/aidl/default/Android.bp
@@ -57,7 +57,6 @@
     shared_libs: [
         "libbinder_ndk",
         "liblog",
-        "libvndksupport",
     ],
     header_libs: ["media_plugin_headers"],
 }
@@ -81,7 +80,8 @@
 
 cc_fuzz {
     name: "android.hardware.cas-service_fuzzer",
-    vendor: true,
+    // TODO(b/307611931): avoid fuzzing on vendor until hermiticity issue is fixed
+    // vendor: true,
 
     defaults: ["service_fuzzer_defaults"],
     srcs: ["fuzzer.cpp"],
diff --git a/cas/aidl/default/SharedLibrary.cpp b/cas/aidl/default/SharedLibrary.cpp
index 6322ff3..c12d17d 100644
--- a/cas/aidl/default/SharedLibrary.cpp
+++ b/cas/aidl/default/SharedLibrary.cpp
@@ -19,7 +19,6 @@
 #include "SharedLibrary.h"
 #include <dlfcn.h>
 #include <utils/Log.h>
-#include <vndksupport/linker.h>
 
 namespace aidl {
 namespace android {
@@ -27,12 +26,12 @@
 namespace cas {
 
 SharedLibrary::SharedLibrary(const String8& path) {
-    mLibHandle = android_load_sphal_library(path.c_str(), RTLD_NOW);
+    mLibHandle = dlopen(path.c_str(), RTLD_NOW);
 }
 
 SharedLibrary::~SharedLibrary() {
     if (mLibHandle != NULL) {
-        android_unload_sphal_library(mLibHandle);
+        dlclose(mLibHandle);
         mLibHandle = NULL;
     }
 }
diff --git a/cas/aidl/default/manifest.json b/cas/aidl/default/manifest.json
index 16b4f67..cdcecb2 100644
--- a/cas/aidl/default/manifest.json
+++ b/cas/aidl/default/manifest.json
@@ -1,9 +1,8 @@
 {
     "name": "com.android.hardware.cas",
     "version": 1,
-    // For CAS HAL to open plugins from /vendor/lib, "vendor" namespace should be imported.
-    // ":sphal" is an alias for the "vendor" namespace in Vendor APEX.
+    // For CAS HAL to open plugins from /vendor/lib/mediacas
     "requireNativeLibs": [
-        ":sphal"
+        ":mediacas"
     ]
 }
diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml
index 3d55da9..99dcdbb 100644
--- a/compatibility_matrices/compatibility_matrix.8.xml
+++ b/compatibility_matrices/compatibility_matrix.8.xml
@@ -360,6 +360,18 @@
             <instance>software</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.media.omx</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOmx</name>
+            <instance>default</instance>
+        </interface>
+        <interface>
+            <name>IOmxStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.memtrack</name>
         <version>1</version>
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index da31888..6ed8e8f 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -509,6 +509,14 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true" updatable-via-apex="true">
+        <name>android.hardware.security.authgraph</name>
+        <version>1</version>
+        <interface>
+            <name>IAuthGraphKeyExchange</name>
+            <instance>nonsecure</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.secureclock</name>
         <version>1</version>
         <interface>
diff --git a/gatekeeper/aidl/Android.bp b/gatekeeper/aidl/Android.bp
index b050f6a..169a7d5 100644
--- a/gatekeeper/aidl/Android.bp
+++ b/gatekeeper/aidl/Android.bp
@@ -25,6 +25,9 @@
         cpp: {
             enabled: false,
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
diff --git a/graphics/composer/aidl/vts/Android.bp b/graphics/composer/aidl/vts/Android.bp
index 88b5de4..60360fd 100644
--- a/graphics/composer/aidl/vts/Android.bp
+++ b/graphics/composer/aidl/vts/Android.bp
@@ -54,7 +54,6 @@
         "libgui",
         "libhidlbase",
         "libprocessgroup",
-        "libtinyxml2",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.1",
         "android.hardware.graphics.mapper@3.0",
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index b047220..9b849cc 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -31,12 +31,6 @@
 #include "RenderEngineVts.h"
 #include "VtsComposerClient.h"
 
-// tinyxml2 does implicit conversions >:(
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#include <tinyxml2.h>
-#pragma clang diagnostic pop
-
 namespace aidl::android::hardware::graphics::composer3::vts {
 namespace {
 
@@ -129,76 +123,6 @@
         return {false, graphicBuffer};
     }
 
-    uint64_t getStableDisplayId(int64_t display) {
-        const auto& [status, identification] =
-                mComposerClient->getDisplayIdentificationData(display);
-        EXPECT_TRUE(status.isOk());
-
-        if (const auto info = ::android::parseDisplayIdentificationData(
-                    static_cast<uint8_t>(identification.port), identification.data)) {
-            return info->id.value;
-        }
-
-        return ::android::PhysicalDisplayId::fromPort(static_cast<uint8_t>(identification.port))
-                .value;
-    }
-
-    // Gets the per-display XML config
-    std::unique_ptr<tinyxml2::XMLDocument> getDisplayConfigXml(int64_t display) {
-        std::stringstream pathBuilder;
-        pathBuilder << "/vendor/etc/displayconfig/display_id_" << getStableDisplayId(display)
-                    << ".xml";
-        const std::string path = pathBuilder.str();
-        auto document = std::make_unique<tinyxml2::XMLDocument>();
-        const tinyxml2::XMLError error = document->LoadFile(path.c_str());
-        if (error == tinyxml2::XML_SUCCESS) {
-            return document;
-        } else {
-            return nullptr;
-        }
-    }
-
-    // Gets the max display brightness for this display.
-    // If the display config xml does not exist, then assume that the display is not well-configured
-    // enough to provide a display brightness, so return nullopt.
-    std::optional<float> getMaxDisplayBrightnessNits(int64_t display) {
-        const auto document = getDisplayConfigXml(display);
-        if (!document) {
-            // Assume the device doesn't support display brightness
-            return std::nullopt;
-        }
-
-        const auto root = document->RootElement();
-        if (!root) {
-            // If there's somehow no root element, then this isn't a valid config
-            return std::nullopt;
-        }
-
-        const auto screenBrightnessMap = root->FirstChildElement("screenBrightnessMap");
-        if (!screenBrightnessMap) {
-            // A valid display config must have a screen brightness map
-            return std::nullopt;
-        }
-
-        auto point = screenBrightnessMap->FirstChildElement("point");
-        float maxNits = -1.f;
-        while (point != nullptr) {
-            const auto nits = point->FirstChildElement("nits");
-            if (nits) {
-                maxNits = std::max(maxNits, nits->FloatText(-1.f));
-            }
-            point = point->NextSiblingElement("point");
-        }
-
-        if (maxNits < 0.f) {
-            // If we got here, then there were no point elements containing a nit value, so this
-            // config isn't valid
-            return std::nullopt;
-        }
-
-        return maxNits;
-    }
-
     void writeLayers(const std::vector<std::shared_ptr<TestLayer>>& layers) {
         for (const auto& layer : layers) {
             layer->write(*mWriter);
@@ -957,32 +881,6 @@
 }
 
 TEST_P(GraphicsCompositionTest, SetLayerBrightnessDims) {
-    const auto& [status, capabilities] =
-            mComposerClient->getDisplayCapabilities(getPrimaryDisplayId());
-    ASSERT_TRUE(status.isOk());
-
-    const bool brightnessSupport = std::find(capabilities.begin(), capabilities.end(),
-                                             DisplayCapability::BRIGHTNESS) != capabilities.end();
-
-    if (!brightnessSupport) {
-        GTEST_SUCCEED() << "Cannot verify dimming behavior without brightness support";
-        return;
-    }
-
-    const std::optional<float> maxBrightnessNitsOptional =
-            getMaxDisplayBrightnessNits(getPrimaryDisplayId());
-
-    ASSERT_TRUE(maxBrightnessNitsOptional.has_value());
-
-    const float maxBrightnessNits = *maxBrightnessNitsOptional;
-
-    // Preconditions to successfully run are knowing the max brightness and successfully applying
-    // the max brightness
-    ASSERT_GT(maxBrightnessNits, 0.f);
-    mWriter->setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 1.f, maxBrightnessNits);
-    execute();
-    ASSERT_TRUE(mReader.takeErrors().empty());
-
     for (ColorMode mode : mTestColorModes) {
         EXPECT_TRUE(mComposerClient
                             ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC)
@@ -999,11 +897,14 @@
         const common::Rect redRect = {0, 0, getDisplayWidth(), getDisplayHeight() / 2};
         const common::Rect dimmerRedRect = {0, getDisplayHeight() / 2, getDisplayWidth(),
                                             getDisplayHeight()};
+
+        static constexpr float kMaxBrightnessNits = 300.f;
+
         const auto redLayer =
                 std::make_shared<TestColorLayer>(mComposerClient, getPrimaryDisplayId());
         redLayer->setColor(RED);
         redLayer->setDisplayFrame(redRect);
-        redLayer->setWhitePointNits(maxBrightnessNits);
+        redLayer->setWhitePointNits(kMaxBrightnessNits);
         redLayer->setBrightness(1.f);
 
         const auto dimmerRedLayer =
@@ -1013,7 +914,7 @@
         // Intentionally use a small dimming ratio as some implementations may be more likely to
         // kick into GPU composition to apply dithering when the dimming ratio is high.
         static constexpr float kDimmingRatio = 0.9f;
-        dimmerRedLayer->setWhitePointNits(maxBrightnessNits * kDimmingRatio);
+        dimmerRedLayer->setWhitePointNits(kMaxBrightnessNits * kDimmingRatio);
         dimmerRedLayer->setBrightness(kDimmingRatio);
 
         const std::vector<std::shared_ptr<TestLayer>> layers = {redLayer, dimmerRedLayer};
diff --git a/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperProvider.h b/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperProvider.h
index 957fdc9..c4d1a0d 100644
--- a/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperProvider.h
+++ b/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperProvider.h
@@ -106,15 +106,15 @@
     static_assert(std::is_constructible_v<IMPL>, "Implementation must have a no-args constructor");
 
     std::once_flag mLoadOnceFlag;
-    std::optional<IMPL> mImpl;
-    AIMapper mMapper = {};
+    IMPL* _Nullable mImpl;
+    AIMapper* _Nullable mMapper;
 
     static IMPL& impl() {
         return *reinterpret_cast<IMapperProvider<IMPL>*>(provider::sIMapperInstance)->mImpl;
     }
 
     void bindV5() {
-        mMapper.v5 = {
+        mMapper->v5 = {
                 .importBuffer = [](const native_handle_t* _Nonnull handle,
                                    buffer_handle_t _Nullable* _Nonnull outBufferHandle)
                         -> AIMapper_Error { return impl().importBuffer(handle, outBufferHandle); },
@@ -208,13 +208,14 @@
             LOG_ALWAYS_FATAL_IF(provider::sIMapperInstance != nullptr,
                                 "AIMapper implementation already loaded!");
             provider::sIMapperInstance = this;
-            mImpl.emplace();
-            mMapper.version = IMPL::version;
+            mImpl = new IMPL();
+            mMapper = new AIMapper();
+            mMapper->version = IMPL::version;
             if (IMPL::version >= AIMAPPER_VERSION_5) {
                 bindV5();
             }
         });
-        *outImplementation = &mMapper;
+        *outImplementation = mMapper;
         return AIMAPPER_ERROR_NONE;
     }
 };
diff --git a/input/processor/aidl/default/Android.bp b/input/processor/aidl/default/Android.bp
index f485597..bdd27e2 100644
--- a/input/processor/aidl/default/Android.bp
+++ b/input/processor/aidl/default/Android.bp
@@ -28,27 +28,54 @@
     ],
 }
 
-filegroup {
+prebuilt_etc {
     name: "android.hardware.input.processor.xml",
-    srcs: ["android.hardware.input.processor.xml"],
+    src: "android.hardware.input.processor.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
+
+prebuilt_etc {
+    name: "inputprocessor-default.rc",
+    src: "inputprocessor-default.rc",
+    installable: false,
 }
 
 cc_binary {
     name: "android.hardware.input.processor-service.example",
     relative_install_path: "hw",
-    init_rc: ["inputprocessor-default.rc"],
-    vintf_fragments: [":android.hardware.input.processor.xml"],
     vendor: true,
+    installable: false, // installed in APEX
+
+    stl: "c++_static",
     shared_libs: [
-        "libbase",
         "libbinder_ndk",
         "liblog",
-        "libutils",
-        "android.hardware.input.common-V1-ndk",
-        "android.hardware.input.processor-V1-ndk",
     ],
     static_libs: [
+        "android.hardware.input.common-V1-ndk",
+        "android.hardware.input.processor-V1-ndk",
+        "libbase",
         "libinputprocessorexampleimpl",
+        "libutils",
     ],
     srcs: ["main.cpp"],
 }
+
+apex {
+    name: "com.android.hardware.input.processor",
+    file_contexts: "apex_file_contexts",
+    manifest: "apex_manifest.json",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
+    updatable: false,
+    vendor: true,
+
+    binaries: [
+        "android.hardware.input.processor-service.example",
+    ],
+    prebuilts: [
+        "android.hardware.input.processor.xml",
+        "inputprocessor-default.rc",
+    ],
+}
diff --git a/input/processor/aidl/default/apex_file_contexts b/input/processor/aidl/default/apex_file_contexts
new file mode 100644
index 0000000..bd2945a
--- /dev/null
+++ b/input/processor/aidl/default/apex_file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                                          u:object_r:vendor_file:s0
+/etc(/.*)?                                                      u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.input\.processor-service\.example    u:object_r:hal_input_processor_default_exec:s0
diff --git a/input/processor/aidl/default/apex_manifest.json b/input/processor/aidl/default/apex_manifest.json
new file mode 100644
index 0000000..2fe0a1d
--- /dev/null
+++ b/input/processor/aidl/default/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+    "name": "com.android.hardware.input.processor",
+    "version": 1
+}
\ No newline at end of file
diff --git a/input/processor/aidl/default/inputprocessor-default.rc b/input/processor/aidl/default/inputprocessor-default.rc
index bcc6c02..ade0f11 100644
--- a/input/processor/aidl/default/inputprocessor-default.rc
+++ b/input/processor/aidl/default/inputprocessor-default.rc
@@ -1,4 +1,4 @@
-service vendor.inputprocessor-default /vendor/bin/hw/android.hardware.input.processor-service.example
+service vendor.inputprocessor-default /apex/com.android.hardware.input.processor/bin/hw/android.hardware.input.processor-service.example
     class hal
     user nobody
     group nobody
\ No newline at end of file
diff --git a/keymaster/4.0/support/fuzzer/keymaster4_utils_fuzzer.cpp b/keymaster/4.0/support/fuzzer/keymaster4_utils_fuzzer.cpp
index bf074e8..55c2630 100644
--- a/keymaster/4.0/support/fuzzer/keymaster4_utils_fuzzer.cpp
+++ b/keymaster/4.0/support/fuzzer/keymaster4_utils_fuzzer.cpp
@@ -46,33 +46,42 @@
     support::getOsVersion();
     support::getOsPatchlevel();
 
-    VerificationToken token;
-    token.challenge = mFdp->ConsumeIntegral<uint64_t>();
-    token.timestamp = mFdp->ConsumeIntegral<uint64_t>();
-    token.securityLevel = mFdp->PickValueInArray(kSecurityLevel);
-    size_t vectorSize = mFdp->ConsumeIntegralInRange<size_t>(0, kMaxVectorSize);
-    token.mac.resize(vectorSize);
-    for (size_t n = 0; n < vectorSize; ++n) {
-        token.mac[n] = n;
+    while (mFdp->remaining_bytes() > 0) {
+        auto keymaster_function = mFdp->PickValueInArray<const std::function<void()>>({
+                [&]() {
+                    VerificationToken token;
+                    token.challenge = mFdp->ConsumeIntegral<uint64_t>();
+                    token.timestamp = mFdp->ConsumeIntegral<uint64_t>();
+                    token.securityLevel = mFdp->PickValueInArray(kSecurityLevel);
+                    size_t vectorSize = mFdp->ConsumeIntegralInRange<size_t>(0, kMaxVectorSize);
+                    token.mac.resize(vectorSize);
+                    for (size_t n = 0; n < vectorSize; ++n) {
+                        token.mac[n] = mFdp->ConsumeIntegral<uint8_t>();
+                    }
+                    std::optional<std::vector<uint8_t>> serialized =
+                            serializeVerificationToken(token);
+                    if (serialized.has_value()) {
+                        std::optional<VerificationToken> deserialized =
+                                deserializeVerificationToken(serialized.value());
+                    }
+                },
+                [&]() {
+                    std::vector<uint8_t> dataVector;
+                    size_t size = mFdp->ConsumeIntegralInRange<size_t>(0, sizeof(hw_auth_token_t));
+                    dataVector = mFdp->ConsumeBytes<uint8_t>(size);
+                    support::blob2hidlVec(dataVector.data(), dataVector.size());
+                    support::blob2hidlVec(dataVector);
+                    HardwareAuthToken authToken = support::hidlVec2AuthToken(dataVector);
+                    hidl_vec<uint8_t> volatile hidlVector = support::authToken2HidlVec(authToken);
+                },
+                [&]() {
+                    std::string str = mFdp->ConsumeRandomLengthString(kMaxCharacters);
+                    support::blob2hidlVec(str);
+                },
+        });
+        keymaster_function();
     }
-    std::optional<std::vector<uint8_t>> serialized = serializeVerificationToken(token);
-    if (serialized.has_value()) {
-        std::optional<VerificationToken> deserialized =
-                deserializeVerificationToken(serialized.value());
-    }
-
-    std::vector<uint8_t> dataVector;
-    size_t size = mFdp->ConsumeIntegralInRange<size_t>(0, sizeof(hw_auth_token_t));
-    dataVector = mFdp->ConsumeBytes<uint8_t>(size);
-    support::blob2hidlVec(dataVector.data(), dataVector.size());
-
-    support::blob2hidlVec(dataVector);
-
-    std::string str = mFdp->ConsumeRandomLengthString(kMaxCharacters);
-    support::blob2hidlVec(str);
-
-    HardwareAuthToken authToken = support::hidlVec2AuthToken(dataVector);
-    hidl_vec<uint8_t> volatile hidlVector = support::authToken2HidlVec(authToken);
+    return;
 }
 
 void KeyMaster4UtilsFuzzer::process(const uint8_t* data, size_t size) {
diff --git a/media/OWNERS b/media/OWNERS
index 71a53ef..01b440a 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -1,7 +1,6 @@
 # Bug component: 25690
 
 # Media team
-jgus@google.com
 lajos@google.com
 taklee@google.com
 wonsik@google.com
diff --git a/media/c2/aidl/Android.bp b/media/c2/aidl/Android.bp
index a153b72..3c0915d 100644
--- a/media/c2/aidl/Android.bp
+++ b/media/c2/aidl/Android.bp
@@ -41,5 +41,12 @@
                 "libnativewindow",
             ],
         },
+        rust: {
+            min_sdk_version: "31",
+            enabled: true,
+            additional_rustlibs: [
+                "libnativewindow_rs",
+            ],
+        },
     },
 }
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl
index c7d8a97..7d58340 100644
--- a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl
@@ -49,8 +49,12 @@
     long blockPoolId;
     android.hardware.media.c2.IConfigurable configurable;
   }
+  parcelable C2AidlGbAllocator {
+    android.hardware.media.c2.IGraphicBufferAllocator igba;
+    ParcelFileDescriptor waitableFd;
+  }
   union BlockPoolAllocator {
     int allocatorId;
-    android.hardware.media.c2.IGraphicBufferAllocator igba;
+    android.hardware.media.c2.IComponent.C2AidlGbAllocator allocator;
   }
 }
diff --git a/media/c2/aidl/android/hardware/media/c2/IComponent.aidl b/media/c2/aidl/android/hardware/media/c2/IComponent.aidl
index a330d46..e96cae5 100644
--- a/media/c2/aidl/android/hardware/media/c2/IComponent.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IComponent.aidl
@@ -21,6 +21,8 @@
 import android.hardware.media.c2.IConfigurable;
 import android.hardware.media.c2.IGraphicBufferAllocator;
 import android.hardware.media.c2.WorkBundle;
+import android.os.ParcelFileDescriptor;
+
 
 /**
  * Interface for an AIDL Codec2 component.
@@ -45,6 +47,18 @@
     }
 
     /**
+     * C2AIDL allocator interface along with a waitable fd.
+     *
+     * The interface is used from a specific type of C2BlockPool to allocate
+     * graphic blocks. the waitable fd is used to create a specific type of
+     * C2Fence which can be used for waiting until to allocate is not blocked.
+     */
+    parcelable C2AidlGbAllocator {
+        IGraphicBufferAllocator igba;
+        ParcelFileDescriptor waitableFd;
+    }
+
+    /**
      * Allocator for C2BlockPool.
      *
      * C2BlockPool will use a C2Allocator which is specified by an id.
@@ -52,7 +66,7 @@
      */
     union BlockPoolAllocator {
         int allocatorId;
-        IGraphicBufferAllocator igba;
+        C2AidlGbAllocator allocator;
     }
 
     /**
diff --git a/nfc/1.0/Android.bp b/nfc/1.0/Android.bp
index 55c8639..ef12c7c 100644
--- a/nfc/1.0/Android.bp
+++ b/nfc/1.0/Android.bp
@@ -22,4 +22,8 @@
     ],
     gen_java: true,
     gen_java_constants: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.nfcservices",
+    ],
 }
diff --git a/nfc/1.1/Android.bp b/nfc/1.1/Android.bp
index a8463cf..65da2a0 100644
--- a/nfc/1.1/Android.bp
+++ b/nfc/1.1/Android.bp
@@ -22,4 +22,8 @@
         "android.hidl.base@1.0",
     ],
     gen_java: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.nfcservices",
+    ],
 }
diff --git a/nfc/1.2/Android.bp b/nfc/1.2/Android.bp
index 4831ab9..8ad93f9 100644
--- a/nfc/1.2/Android.bp
+++ b/nfc/1.2/Android.bp
@@ -22,4 +22,8 @@
         "android.hidl.base@1.0",
     ],
     gen_java: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.nfcservices",
+    ],
 }
diff --git a/nfc/aidl/Android.bp b/nfc/aidl/Android.bp
index 08ec5fe..dae9f29 100644
--- a/nfc/aidl/Android.bp
+++ b/nfc/aidl/Android.bp
@@ -34,6 +34,13 @@
             sdk_version: "module_current",
             enabled: false,
         },
+	ndk: {
+            enabled: true,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.nfcservices",
+            ],
+        },
         rust: {
             enabled: true,
         },
diff --git a/radio/aidl/vts/radio_data_test.cpp b/radio/aidl/vts/radio_data_test.cpp
index 0fb2fb4..f31c254 100644
--- a/radio/aidl/vts/radio_data_test.cpp
+++ b/radio/aidl/vts/radio_data_test.cpp
@@ -214,7 +214,8 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
                                      {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
                                       RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
-        if (radioRsp_data->setupDataCallResult.trafficDescriptors.size() <= 0) {
+        if (radioRsp_data->setupDataCallResult.trafficDescriptors.size() <= 0 ||
+            !radioRsp_data->setupDataCallResult.trafficDescriptors[0].osAppId.has_value()) {
             return;
         }
         EXPECT_EQ(trafficDescriptor.osAppId.value().osAppId,
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
index 06bcd1f..6643c1e 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -119,7 +119,7 @@
                  RadioError::REQUEST_NOT_SUPPORTED, RadioError::NO_RESOURCES}));
         if (radioRsp_network->rspInfo.error == RadioError::NONE) {
             // verify we get the value we set
-            ASSERT_EQ(radioRsp_network->networkTypeBitmapResponse, allowedNetworkTypesBitmap);
+            EXPECT_EQ(radioRsp_network->networkTypeBitmapResponse, allowedNetworkTypesBitmap);
         }
     }
 
diff --git a/rebootescrow/aidl/default/Android.bp b/rebootescrow/aidl/default/Android.bp
index 4409314..7f9b6d6 100644
--- a/rebootescrow/aidl/default/Android.bp
+++ b/rebootescrow/aidl/default/Android.bp
@@ -42,10 +42,10 @@
 
 cc_binary {
     name: "android.hardware.rebootescrow-service.default",
-    init_rc: ["rebootescrow-default.rc"],
     relative_install_path: "hw",
-    vintf_fragments: ["rebootescrow-default.xml"],
     vendor: true,
+    installable: false, // installed in APEX
+
     srcs: [
         "service.cpp",
     ],
@@ -53,12 +53,14 @@
         "-Wall",
         "-Werror",
     ],
+    stl: "c++_static",
     shared_libs: [
-        "libbase",
         "libbinder_ndk",
-        "android.hardware.rebootescrow-V1-ndk",
+        "liblog",
     ],
     static_libs: [
+        "android.hardware.rebootescrow-V1-ndk",
+        "libbase",
         "libhadamardutils",
         "librebootescrowdefaultimpl",
     ],
@@ -97,3 +99,35 @@
     ],
     test_suites: ["device-tests"],
 }
+
+prebuilt_etc {
+    name: "rebootescrow-default.rc",
+    src: "rebootescrow-default.rc",
+    installable: false,
+}
+
+prebuilt_etc {
+    name: "rebootescrow-default.xml",
+    src: "rebootescrow-default.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
+
+apex {
+    name: "com.android.hardware.rebootescrow",
+    manifest: "apex_manifest.json",
+    file_contexts: "apex_file_contexts",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
+    vendor: true,
+    updatable: false,
+
+    binaries: [
+        "android.hardware.rebootescrow-service.default",
+    ],
+    prebuilts: [
+        "rebootescrow-default.rc",
+        "rebootescrow-default.xml",
+        "android.hardware.reboot_escrow.prebuilt.xml", // <feature>
+    ],
+}
diff --git a/rebootescrow/aidl/default/apex_file_contexts b/rebootescrow/aidl/default/apex_file_contexts
new file mode 100644
index 0000000..aa84984
--- /dev/null
+++ b/rebootescrow/aidl/default/apex_file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                                      u:object_r:vendor_file:s0
+/etc(/.*)?                                                  u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.rebootescrow-service\.default    u:object_r:hal_rebootescrow_default_exec:s0
diff --git a/rebootescrow/aidl/default/apex_manifest.json b/rebootescrow/aidl/default/apex_manifest.json
new file mode 100644
index 0000000..8be495b
--- /dev/null
+++ b/rebootescrow/aidl/default/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+    "name": "com.android.hardware.rebootescrow",
+    "version": 1
+}
\ No newline at end of file
diff --git a/rebootescrow/aidl/default/rebootescrow-default.rc b/rebootescrow/aidl/default/rebootescrow-default.rc
index ad90465..024dd6d 100644
--- a/rebootescrow/aidl/default/rebootescrow-default.rc
+++ b/rebootescrow/aidl/default/rebootescrow-default.rc
@@ -1,4 +1,4 @@
-service vendor.rebootescrow-default /vendor/bin/hw/android.hardware.rebootescrow-service.default
+service vendor.rebootescrow-default /apex/com.android.hardware.rebootescrow/bin/hw/android.hardware.rebootescrow-service.default
     interface aidl android.hardware.rebootescrow.IRebootEscrow/default
     class hal
     user system
diff --git a/secure_element/aidl/default/Android.bp b/secure_element/aidl/default/Android.bp
index d1bb393..b382822 100644
--- a/secure_element/aidl/default/Android.bp
+++ b/secure_element/aidl/default/Android.bp
@@ -11,14 +11,50 @@
     name: "android.hardware.secure_element-service.example",
     relative_install_path: "hw",
     vendor: true,
-    init_rc: ["secure_element.rc"],
-    vintf_fragments: ["secure_element.xml"],
+    installable: false, // installed in APEX
+
+    stl: "c++_static",
     shared_libs: [
-        "libbase",
         "libbinder_ndk",
+        "liblog",
+    ],
+    static_libs: [
         "android.hardware.secure_element-V1-ndk",
+        "libbase",
     ],
     srcs: [
         "main.cpp",
     ],
 }
+
+prebuilt_etc {
+    name: "secure_element.rc",
+    src: "secure_element.rc",
+    installable: false,
+}
+
+prebuilt_etc {
+    name: "secure_element.xml",
+    src: "secure_element.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
+
+apex {
+    name: "com.android.hardware.secure_element",
+    manifest: "apex_manifest.json",
+    file_contexts: "apex_file_contexts",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
+    vendor: true,
+    updatable: false,
+
+    binaries: [
+        "android.hardware.secure_element-service.example",
+    ],
+    prebuilts: [
+        "secure_element.rc",
+        "secure_element.xml",
+        "android.hardware.se.omapi.ese.prebuilt.xml", // <feature>
+    ],
+}
diff --git a/secure_element/aidl/default/apex_file_contexts b/secure_element/aidl/default/apex_file_contexts
new file mode 100644
index 0000000..e9e811e
--- /dev/null
+++ b/secure_element/aidl/default/apex_file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                                      u:object_r:vendor_file:s0
+/etc(/.*)?                                                  u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.secure_element-service\.example  u:object_r:hal_secure_element_default_exec:s0
\ No newline at end of file
diff --git a/secure_element/aidl/default/apex_manifest.json b/secure_element/aidl/default/apex_manifest.json
new file mode 100644
index 0000000..6e04c11
--- /dev/null
+++ b/secure_element/aidl/default/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+    "name": "com.android.hardware.secure_element",
+    "version": 1
+}
\ No newline at end of file
diff --git a/secure_element/aidl/default/secure_element.rc b/secure_element/aidl/default/secure_element.rc
index 7d21666..b74b2ee 100644
--- a/secure_element/aidl/default/secure_element.rc
+++ b/secure_element/aidl/default/secure_element.rc
@@ -1,4 +1,4 @@
-service vendor.secure_element /vendor/bin/hw/android.hardware.secure_element-service.example
+service vendor.secure_element /apex/com.android.hardware.secure_element/bin/hw/android.hardware.secure_element-service.example
     class hal
     user nobody
     group nobody
diff --git a/security/authgraph/aidl/Android.bp b/security/authgraph/aidl/Android.bp
new file mode 100644
index 0000000..d94f640
--- /dev/null
+++ b/security/authgraph/aidl/Android.bp
@@ -0,0 +1,88 @@
+// Copyright (C) 2023 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"],
+}
+
+aidl_interface {
+    name: "android.hardware.security.authgraph",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/security/authgraph/*.aidl",
+    ],
+    stability: "vintf",
+    frozen: false,
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            apps_enabled: false,
+        },
+        rust: {
+            enabled: true,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.virt",
+            ],
+        },
+    },
+}
+
+// cc_defaults that includes the latest Authgraph AIDL library.
+// Modules that depend on Authgraph directly can include this cc_defaults to avoid
+// managing dependency versions explicitly.
+cc_defaults {
+    name: "authgraph_use_latest_hal_aidl_ndk_static",
+    static_libs: [
+        "android.hardware.security.authgraph-V1-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "authgraph_use_latest_hal_aidl_ndk_shared",
+    shared_libs: [
+        "android.hardware.security.authgraph-V1-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "authgraph_use_latest_hal_aidl_cpp_static",
+    static_libs: [
+        "android.hardware.security.authgraph-V1-cpp",
+    ],
+}
+
+cc_defaults {
+    name: "authgraph_use_latest_hal_aidl_cpp_shared",
+    shared_libs: [
+        "android.hardware.security.authgraph-V1-cpp",
+    ],
+}
+
+// A rust_defaults that includes the latest Authgraph AIDL library.
+// Modules that depend on Authgraph directly can include this rust_defaults to avoid
+// managing dependency versions explicitly.
+rust_defaults {
+    name: "authgraph_use_latest_hal_aidl_rust",
+    rustlibs: [
+        "android.hardware.security.authgraph-V1-rust",
+    ],
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Arc.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Arc.aidl
new file mode 100644
index 0000000..dc86fbd
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Arc.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable Arc {
+  byte[] arc;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Error.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Error.aidl
new file mode 100644
index 0000000..1a78b54
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Error.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum Error {
+  OK = 0,
+  INVALID_PEER_NONCE = (-1) /* -1 */,
+  INVALID_PEER_KE_KEY = (-2) /* -2 */,
+  INVALID_IDENTITY = (-3) /* -3 */,
+  INVALID_CERT_CHAIN = (-4) /* -4 */,
+  INVALID_SIGNATURE = (-5) /* -5 */,
+  INVALID_KE_KEY = (-6) /* -6 */,
+  INVALID_PUB_KEY_IN_KEY = (-7) /* -7 */,
+  INVALID_PRIV_KEY_ARC_IN_KEY = (-8) /* -8 */,
+  INVALID_SHARED_KEY_ARCS = (-9) /* -9 */,
+  MEMORY_ALLOCATION_FAILED = (-10) /* -10 */,
+  INCOMPATIBLE_PROTOCOL_VERSION = (-11) /* -11 */,
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl
new file mode 100644
index 0000000..2c56f33
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+/* @hide */
+@VintfStability
+interface IAuthGraphKeyExchange {
+  android.hardware.security.authgraph.SessionInitiationInfo create();
+  android.hardware.security.authgraph.KeInitResult init(in android.hardware.security.authgraph.PubKey peerPubKey, in android.hardware.security.authgraph.Identity peerId, in byte[] peerNonce, in int peerVersion);
+  android.hardware.security.authgraph.SessionInfo finish(in android.hardware.security.authgraph.PubKey peerPubKey, in android.hardware.security.authgraph.Identity peerId, in android.hardware.security.authgraph.SessionIdSignature peerSignature, in byte[] peerNonce, in int peerVersion, in android.hardware.security.authgraph.Key ownKey);
+  android.hardware.security.authgraph.Arc[2] authenticationComplete(in android.hardware.security.authgraph.SessionIdSignature peerSignature, in android.hardware.security.authgraph.Arc[2] sharedKeys);
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Identity.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Identity.aidl
new file mode 100644
index 0000000..bd5453e
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Identity.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable Identity {
+  byte[] identity;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/KeInitResult.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/KeInitResult.aidl
new file mode 100644
index 0000000..8c91523
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/KeInitResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable KeInitResult {
+  android.hardware.security.authgraph.SessionInitiationInfo sessionInitiationInfo;
+  android.hardware.security.authgraph.SessionInfo sessionInfo;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Key.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Key.aidl
new file mode 100644
index 0000000..5b4ebbf
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Key.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable Key {
+  @nullable android.hardware.security.authgraph.PubKey pubKey;
+  @nullable android.hardware.security.authgraph.Arc arcFromPBK;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PlainPubKey.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PlainPubKey.aidl
new file mode 100644
index 0000000..f070bfa
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PlainPubKey.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable PlainPubKey {
+  byte[] plainPubKey;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PubKey.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PubKey.aidl
new file mode 100644
index 0000000..4c3376e
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PubKey.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+union PubKey {
+  android.hardware.security.authgraph.PlainPubKey plainKey;
+  android.hardware.security.authgraph.SignedPubKey signedKey;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionIdSignature.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionIdSignature.aidl
new file mode 100644
index 0000000..6dabc0a
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionIdSignature.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable SessionIdSignature {
+  byte[] signature;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInfo.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInfo.aidl
new file mode 100644
index 0000000..427962b
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable SessionInfo {
+  android.hardware.security.authgraph.Arc[2] sharedKeys;
+  byte[] sessionId;
+  android.hardware.security.authgraph.SessionIdSignature signature;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInitiationInfo.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInitiationInfo.aidl
new file mode 100644
index 0000000..bf55e74
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInitiationInfo.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable SessionInitiationInfo {
+  android.hardware.security.authgraph.Key key;
+  android.hardware.security.authgraph.Identity identity;
+  byte[] nonce;
+  int version;
+}
diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SignedPubKey.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SignedPubKey.aidl
new file mode 100644
index 0000000..3dbaed8
--- /dev/null
+++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SignedPubKey.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable SignedPubKey {
+  byte[] signedPubKey;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Arc.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.aidl
new file mode 100644
index 0000000..855ce5c
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+
+/**
+ * This is the definition of the data format of an Arc.
+ * @hide
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable Arc {
+    /**
+     * The messages exchanged between the domains in the AuthGraph protocol are called Arcs.
+     * An arc is simply AES-GCM. Encryption of a payload P with a key K and additional
+     * authentication data (AAD) D: (i.e. Arc = Enc(K, P, D)).
+     *
+     * Data is CBOR-encoded according to the `Arc` CDDL definition in Arc.cddl.
+     */
+    byte[] arc;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl
new file mode 100644
index 0000000..4c1b965
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl
@@ -0,0 +1,115 @@
+;
+; Copyright (C) 2023 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.
+;
+Arc = [                            ; COSE_Encrypt0 [RFC9052 s5.2]
+    protected : bstr .cbor ArcProtectedHeaders,
+    unprotected : {
+        5 : bstr .size 12          ; IV
+    },
+    ciphertext : bstr    ; Enc(K, bstr .cbor Payload, encoded ArcEncStruct)
+]
+
+ArcProtectedHeaders = {
+           1 : 3,                  ; Algorithm: AES-GCM mode w/ 256-bit key, 128-bit tag
+    ? -70001 : { + Permission }, ; One or more Permissions
+    ? -70002 : { + Limitation }, ; One or more Limitations
+    ? -70003 : int,   ; Timestamp in milliseconds since some starting point (generally
+                      ; the most recent device boot) which all of the applications within
+                      ; the secure domain must agree upon
+    ? -70004 : bstr .size 16,      ; Nonce used in key exchange methods
+    ? -70005 : PayloadType,        ; Payload type, if needed to disambiguate, when processing an arc
+    ? -70006 : int,                ; Version of the payload structure (if applicable)
+    ? -70007 : int,                ; Sequence number (if needed to prevent replay attacks)
+    ? -70008 : Direction           ; Direction of the encryption key (i.e. whether it is used to
+                                   ; encrypt incoming messages or outgoing messages)
+    ? -70009 : bool,               ; "authentication_completed" - this is used during authenticated
+                                   ; key exchange indicate whether signature verification is done
+    ? -70010 : bstr .size 32       ; "session_id" computed during key exchange protocol
+}
+
+; Permissions indicate what an arc can be used with. Permissions are added to an arc during the
+; `create()` primitive operation and are propagated during `mint` and `snap` primitive operations.
+Permission = &(
+    -4770552 : IdentityEncoded,  ; "source_id" - in the operations performed by a source, the
+                                 ; source adds its own identity to the permissions of an arc.
+    -4770553 : IdentityEncoded,  ; "sink_id" - in the operations performed by a sink, the sink
+                                 ; adds its own identity to the permissions of an arc.
+    -4770555 : [ +IdentityEncoded ]  ; "minting_allowed" - defines the set of TA identities
+                                     ; to whom the payload key is allowed to be minted.
+    -4770556 : bool                  ; "deleted_on_biometric_change" - A Boolean value that
+                                     ; indicates whether an auth key issued from a biometric TA is
+                                     ; invalidated on new biometric enrollment or removal of all
+                                     ; biometrics.
+)
+
+; Limitations indicate what restrictions are applied on the usage of an arc. Permissions are added
+; to an arc during the `create` primitive operation and are propagated during `snap` primitive
+; operation.
+Limitation = &(
+    -4770554 : bstr,      ; "challenge" - is added to an arc that transfers an auth key to a channel
+                          ; key, in order to ensure the freshness of the authentication.
+                          ; A challenge is issued by a sink (e.g. Keymint TA, Biometric TAs).
+)
+
+; INCLUDE Identity.cddl for: Identity
+IdentityEncoded = bstr .cbor Identity
+
+Direction = &(
+    In:  1,
+    Out: 2,
+)
+
+PayloadType = &(
+    SecretKey: 1,
+    Arc: 2,
+    ; Any other payload types should also be defined here
+)
+
+Payload = &(
+    SecretKey,
+    Arc,
+    ; Any other payload formats should also be defined here
+)
+
+SecretKey = &(                     ; One of the payload types of an Arc is a secret key
+    SymmetricKey,
+    ECPrivateKey,    ; Private key of a key pair generated for key exchange
+)
+
+ECPrivateKey = {              ; COSE_Key [RFC9052 s7]
+    1 : 2,                    ; Key type : EC2
+    3 : -25,                  ; Algorithm: ECDH ES w/ HKDF 256 - generate key directly
+ ?  4 : [7],                  ; Key_ops: [derive key]
+   -1 : 1,                    ; Curve: P-256
+ ? -2 : bstr,                 ; x coordinate
+ ? -3 : bstr,                 ; y coordinate
+   -4 : bstr,                 ; private key (d)
+}
+
+SymmetricKey = {              ; COSE_Key [RFC9052 s7] - For symmetric key encryption
+    1 : 4,                    ; Key type : Symmetric
+    3 : 3,                    ; Algorithm : AES-GCM mode w/ 256-bit key, 128-bit tag
+    4 : [ 4 ],                ; Key_ops: [decrypt]
+   -1 : bstr .size 32,        ; Key value (k)
+}
+
+ArcEncStruct = [              ; COSE_Enc_structure [RFC9052 s5.3]
+    context   : "Encrypt0",
+    protected : bstr .cbor ArcProtectedHeaders,
+    external_aad : bstr .size 0,
+]
+
+; INCLUDE generateCertificateRequestV2.cddl for: PubKeyEd25519, PubKeyECDSA256, PubKeyECDSA384
+; from hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/DicePolicy.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/DicePolicy.cddl
new file mode 100644
index 0000000..a7dcbc6
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/DicePolicy.cddl
@@ -0,0 +1,33 @@
+;
+; Copyright (C) 2023 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.
+;
+DicePolicy = [
+    1, ; dice policy version
+    + nodeConstraintList ; for each entry in dice chain
+]
+
+nodeConstraintList = [
+    * nodeConstraint
+]
+
+; We may add a hashConstraint item later
+nodeConstraint = exactMatchConstraint / geConstraint
+
+exactMatchConstraint = [1, keySpec, value]
+geConstraint = [2, keySpec, int]
+
+keySpec = [value+]
+
+value = bool / int / tstr / bstr
\ No newline at end of file
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Error.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/Error.aidl
new file mode 100644
index 0000000..1ad6054
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Error.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+
+/**
+ * AuthGraph error codes. Aidl will return these error codes as service specific errors in
+ * EX_SERVICE_SPECIFIC.
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum Error {
+    /* Success */
+    OK = 0,
+    /* Invalid peer nonce for key exchange */
+    INVALID_PEER_NONCE = -1,
+    /* Invalid key exchange public key by the peer */
+    INVALID_PEER_KE_KEY = -2,
+    /* Invalid identity of the peer */
+    INVALID_IDENTITY = -3,
+    /* Invalid certificate chain in the identity of the peer */
+    INVALID_CERT_CHAIN = -4,
+    /* Invalid signature by the peer */
+    INVALID_SIGNATURE = -5,
+    /* Invalid key exchange key created by a particular party themselves to be used as a handle */
+    INVALID_KE_KEY = -6,
+    /* Invalid public key in the `Key` struct */
+    INVALID_PUB_KEY_IN_KEY = -7,
+    /* Invalid private key arc in the `Key` struct */
+    INVALID_PRIV_KEY_ARC_IN_KEY = -8,
+    /* Invalid shared key arcs */
+    INVALID_SHARED_KEY_ARCS = -9,
+    /* Memory allocation failed */
+    MEMORY_ALLOCATION_FAILED = -10,
+    /* The protocol version negotiated with the sink is incompatible */
+    INCOMPATIBLE_PROTOCOL_VERSION = -11,
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/ExplicitKeyDiceCertChain.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/ExplicitKeyDiceCertChain.cddl
new file mode 100644
index 0000000..3de5617
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/ExplicitKeyDiceCertChain.cddl
@@ -0,0 +1,30 @@
+;
+; Copyright (C) 2023 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.
+;
+ExplicitKeyDiceCertChain = [
+    1, ; version, hopefully will never change
+    DiceCertChainInitialPayload,
+    * DiceChainEntry
+]
+
+DiceCertChainInitialPayload = {
+    -4670552 : bstr .cbor PubKeyEd25519 /
+               bstr .cbor PubKeyECDSA256 /
+               bstr .cbor PubKeyECDSA384 ; subjectPublicKey
+}
+
+; INCLUDE generateCertificateRequestV2.cddl for: PubKeyEd25519, PubKeyECDSA256, PubKeyECDSA384,
+;                                                DiceChainEntry
+; from hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl
new file mode 100644
index 0000000..6ceb09c
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+
+import android.hardware.security.authgraph.Arc;
+import android.hardware.security.authgraph.Identity;
+import android.hardware.security.authgraph.KeInitResult;
+import android.hardware.security.authgraph.Key;
+import android.hardware.security.authgraph.PubKey;
+import android.hardware.security.authgraph.SessionIdSignature;
+import android.hardware.security.authgraph.SessionInfo;
+import android.hardware.security.authgraph.SessionInitiationInfo;
+
+/**
+ * AuthGraph interface definition for authenticated key exchange between two parties: P1 (source)
+ * and P2 (sink).
+ * Pre-requisites: each participant should have a:
+ *     1. Persistent identity - e.g. a signing key pair with a self signed certificate or a DICE
+ *        certificate chain.
+ *     2. A symmetric encryption key kept in memory with per-boot life time of the participant
+ *        (a.k.a per-boot key)
+ *
+ * ErrorCodes are defined in android.hardware.security.authgraph.ErrorCode.aidl.
+ * @hide
+ */
+@VintfStability
+interface IAuthGraphKeyExchange {
+    /**
+     * This method is invoked on P1 (source).
+     * Create an ephermeral EC key pair on NIST curve P-256 and a nonce (of 16 bytes) for
+     * key exchange.
+     *
+     * @return SessionInitiationInfo including the `Key` containing the public key of the created
+     * key pair and an arc from the per-boot key to the private key, the nonce, the persistent
+     * identity and the latest protocol version (i.e. AIDL version) supported.
+     *
+     * Note: The arc from the per-boot key to the private key in `Key` of the return type:
+     * `SessionInitiationInfo` serves two purposes:
+     * i. A mapping to correlate `create` and `finish` calls to P1 in a particular instance of the
+     *    key exchange protocol.
+     * ii.A way to minimize the in-memory storage (P1 can include the nonce in the protected headers
+     *    of the arc).
+     * However, P1 should maintain some form of in-memory record to be able to verify that the input
+     * `Key` sent to `finish` is from an unfinished instance of a key exchange protocol, to prevent
+     * any replay attacks in `finish`.
+     */
+    SessionInitiationInfo create();
+
+    /**
+     * This method is invoked on P2 (sink).
+     * Perform the following steps for key exchange:
+     *     0. If either `peerPubKey`, `peerId`, `peerNonce` is not in the expected format, return
+     *        errors: INVALID_PEER_KE_KEY, INVALID_IDENTITY, INVALID_PEER_NONCE respectively.
+     *     1. Create an ephemeral EC key pair on NIST curve P-256.
+     *     2. Create a nonce (of 16 bytes).
+     *     3. Compute the diffie-hellman shared secret: Z.
+     *     4. Compute a salt = bstr .cbor [
+     *            source_version:    int,                    ; from input `peerVersion`
+     *            sink_pub_key:      bstr .cbor PlainPubKey, ; from step #1
+     *            source_pub_key:    bstr .cbor PlainPubKey, ; from input `peerPubKey`
+     *            sink_nonce:        bstr .size 16,          ; from step #2
+     *            source_nonce:      bstr .size 16,          ; from input `peerNonce`
+     *            sink_cert_chain:   bstr .cbor ExplicitKeyDiceCertChain, ; from own identity
+     *            source_cert_chain: bstr .cbor ExplicitKeyDiceCertChain, ; from input `peerId`
+     *        ]
+     *     5. Extract a cryptographic secret S from Z, using the salt from #4 above.
+     *     6. Derive two symmetric encryption keys of 256 bits with:
+     *        i. b"KE_ENCRYPTION_KEY_SOURCE_TO_SINK" as context for the key used to encrypt incoming
+     *           messages
+     *       ii. b"KE_ENCRYPTION_KEY_SINK_TO_SOURCE" as context for the key used to encrypt outgoing
+     *           messages
+     *     7. Create arcs from the per-boot key to each of the two shared keys from step #6 and
+     *        mark authentication_complete = false in arcs' protected headers.
+     *     8. Derive a MAC key with b"KE_HMAC_KEY" as the context.
+     *     9. Compute session_id_input = bstr .cbor [
+     *            sink_nonce:     bstr .size 16,
+     *            source_nonce:   bstr .size 16,
+     *        ],
+     *     10.Compute a session_id as a 256 bits HMAC over the session_id_input from step#9 with
+     *        the key from step #8.
+     *     11.Create a signature over the session_id from step #10, using the signing key which is
+     *        part of the party's identity.
+     *
+     * @param peerPubKey - the public key of the key pair created by the peer (P1) for key exchange
+     *
+     * @param peerId - the persistent identity of the peer
+     *
+     * @param peerNonce - nonce created by the peer
+     *
+     * @param peerVersion - an integer representing the latest protocol version (i.e. AIDL version)
+     *                      supported by the peer
+     *
+     * @return KeInitResult including the `Key` containing the public key of the created key pair,
+     * the nonce, the persistent identity, two shared key arcs from step #7, session id, signature
+     * over the session id and the negotiated protocol version. The negotiated protocol version
+     * should be less than or equal to the peer's version.
+     *
+     * Note: The two shared key arcs in the return type: `KeInitResult` serves two purposes:
+     * i. A mapping to correlate `init` and `authenticationComplete` calls to P2 in a particular
+     *    instance of the key exchange protocol.
+     * ii.A way to minimize the in-memory storage of P2 allocated for key exchange.
+     * However, P2 should maintain some in-memory record to be able to verify that the input
+     * `sharedkeys` sent to `authenticationComplete` and to any subsequent AuthGraph protocol
+     * methods are valid shared keys agreed with the party identified by `peerId`, to prevent
+     * any replay attacks in `authenticationComplete` and in any subsequent AuthGraph protocol
+     * methods which use the shared keys to encrypt the secret messages.
+     */
+    KeInitResult init(
+            in PubKey peerPubKey, in Identity peerId, in byte[] peerNonce, in int peerVersion);
+
+    /**
+     * This method is invoked on P1 (source).
+     * Perform the following steps:
+     *     0. If either `peerPubKey`, `peerId`, `peerNonce` is not in the expected format, return
+     *        errors: INVALID_PEER_KE_KEY, INVALID_IDENTITY, INVALID_PEER_NONCE respectively. If
+     *        `peerVersion` is greater than the version advertised in `create`, return error:
+     *        INCOMPATIBLE_PROTOCOL_VERSION.
+     *        If `ownKey` is not in the in-memory records for unfinished instances of a key
+     *        exchange protocol, return error: INVALID_KE_KEY. Similarly, if the public key or the
+     *        arc containing the private key in `ownKey` is invalid, return INVALID_PUB_KEY_IN_KEY
+     *        and INVALID_PRIV_KEY_ARC_IN_KEY respectively.
+     *     1. Compute the diffie-hellman shared secret: Z.
+     *     2. Compute a salt = bstr .cbor [
+     *            source_version:    int,                    ; the protocol version used in `create`
+     *            sink_pub_key:      bstr .cbor PlainPubKey, ; from input `peerPubKey`
+     *            source_pub_key:    bstr .cbor PlainPubKey, ; from the output of `create`
+     *            sink_nonce:        bstr .size 16,          ; from input `peerNonce`
+     *            source_nonce:      bstr .size 16,          ; from the output of `create`
+     *            sink_cert_chain:   bstr .cbor ExplicitKeyDiceCertChain, ; from input `peerId`
+     *            source_cert_chain: bstr .cbor ExplicitKeyDiceCertChain, ; from own identity
+     *        ]
+     *     3. Extract a cryptographic secret S from Z, using the salt from #2 above.
+     *     4. Derive two symmetric encryption keys of 256 bits with:
+     *        i. b"KE_ENCRYPTION_KEY_SOURCE_TO_SINK" as context for the key used to encrypt outgoing
+     *           messages
+     *       ii. b"KE_ENCRYPTION_KEY_SINK_TO_SOURCE" as context for the key used to encrypt incoming
+     *           messages
+     *     5. Derive a MAC key with b"KE_HMAC_KEY" as the context.
+     *     6. Compute session_id_input = bstr .cbor [
+     *            sink_nonce:     bstr .size 16,
+     *            source_nonce:   bstr .size 16,
+     *        ],
+     *     7. Compute a session_id as a 256 bits HMAC over the session_id_input from step #6 with
+     *        the key from step #5.
+     *     8. Verify the peer's signature over the session_id from step #7. If successful, proceed,
+     *        otherwise, return error: INVALID_SIGNATURE.
+     *     9. Create arcs from the per-boot key to each of the two shared keys from step #4 and
+     *        mark authentication_complete = true in arcs' protected headers.
+     *     10.Create a signature over the session_id from step #7, using the signing key which is
+     *        part of the party's identity.
+     *
+     * @param peerPubKey - the public key of the key pair created by the peer (P2) for key exchange
+     *
+     * @param peerId - the persistent identity of the peer
+     *
+     * @param peerSignature - the signature created by the peer over the session id computed by the
+     *                        peer
+     *
+     * @param peerNonce - nonce created by the peer
+     *
+     * @param peerVersion - an integer representing the protocol version (i.e. AIDL version)
+     *                      negotiated with the peer
+     *
+     * @param ownKey - the key created by P1 (source) in `create()` for key exchange
+     *
+     * @return SessionInfo including the two shared key arcs from step #9, session id and the
+     * signature over the session id.
+     *
+     * Note: The two shared key arcs in the return type: `SessionInfo` serves two purposes:
+     * i. A mapping to correlate the key exchange protocol taken place with a particular peer and
+     *    subsequent AuthGraph protocols execued with the same peer.
+     * ii.A way to minimize the in-memory storage for shared keys.
+     * However, P1 should maintain some in-memory record to be able to verify that the shared key
+     * arcs sent to any subsequent AuthGraph protocol methods are valid shared keys agreed with the
+     * party identified by `peerId`, to prevent any replay attacks.
+     */
+    SessionInfo finish(in PubKey peerPubKey, in Identity peerId,
+            in SessionIdSignature peerSignature, in byte[] peerNonce, in int peerVersion,
+            in Key ownKey);
+
+    /**
+     * This method is invoked on P2 (sink).
+     * Perform the following steps:
+     *   0. If input `sharedKeys` is invalid (i.e. they cannot be decrypted with P2's per-boot key
+     *      or they are not in P2's in-memory records as valid shared keys agreed with the party
+     *      identified by `peerId`), return error: INVALID_SHARED_KEY_ARCS.
+     *   1. Verify that both shared key arcs have the same session id and peer identity.
+     *   2. Verify the peer's signature over the session id attached to the shared key arcs'
+     *      headers. If successful, proceed, otherwise, return error: INVALID_SIGNATURE.
+     *   3. Mark authentication_complete = true in the shared key arcs' headers
+     *
+     * @param peerSignature - the signature created by the peer over the session id computed by the
+     *                        peer
+     *
+     * @param sharedKeys - two shared key arcs created by P2 in `init`. P2 obtains from the arcs'
+     *                     protected headers, the session id and the peer's identity to verify the
+     *                     peer's signature over the session id.
+     *
+     * @return Arc[] - an array of two updated shared key arcs
+     */
+    Arc[2] authenticationComplete(in SessionIdSignature peerSignature, in Arc[2] sharedKeys);
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Identity.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/Identity.aidl
new file mode 100644
index 0000000..9e350e8
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Identity.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+
+/**
+ * Persistent (versioned) identity of a participant of Authgraph key exchange.
+ * Identity consists of two main parts:
+ *     1. a certificate chain (e.g. a DICE certificate chain)
+ *     2. (optional) a policy specifying how to verify the certificate chain - if a policy is not
+ *        provided, a simple byte-to-byte comparison of the certificate chain is assumed.
+ *
+ * During identity verification, the certificate chain of the identity attached to the access
+ * request is compared against the policy of the identity attached to the persistent resources.
+ *
+ * The usage of policy based identity verification in Authgraph is three-fold:
+ *        1. Retain access to persistent resources for the newer versions of the party who
+ *           created them, even when parts of the certificate chain are updated in the new version.
+ *        2. Deny access to the new persistent resources for the older versions of the party
+ *           who created the new persistent resources.
+ *        3. Trigger rotation of critical keys encrypted in persistent arcs created by the previous
+ *           version of the party, by including an updated policy in the identity attached to the
+ *           access request.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable Identity {
+    /* Data is CBOR-encoded according to the `Identity` CDDL definition in Identity.cddl */
+    byte[] identity;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Identity.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/Identity.cddl
new file mode 100644
index 0000000..0419421
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Identity.cddl
@@ -0,0 +1,23 @@
+;
+; Copyright (C) 2023 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.
+;
+Identity = [
+    1, ; Version
+    cert_chain: bstr .cbor ExplicitKeyDiceCertChain,
+    policy: bstr .cbor DicePolicy / nil,
+]
+
+; INCLUDE ExplicitKeyDiceCertChain.cddl for: ExplicitKeyDiceCertChain
+; INCLUDE DicePolicy.cddl for: DicePolicy
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/KeInitResult.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/KeInitResult.aidl
new file mode 100644
index 0000000..b4ae451
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/KeInitResult.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+
+import android.hardware.security.authgraph.SessionInfo;
+import android.hardware.security.authgraph.SessionInitiationInfo;
+
+/**
+ * The return type for the init() step of authenticated key exchange.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable KeInitResult {
+    /**
+     * Session initiation information.
+     */
+    SessionInitiationInfo sessionInitiationInfo;
+
+    /**
+     * Session information.
+     */
+    SessionInfo sessionInfo;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Key.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/Key.aidl
new file mode 100644
index 0000000..11fe174
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Key.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+
+import android.hardware.security.authgraph.Arc;
+import android.hardware.security.authgraph.PubKey;
+
+/**
+ * The type that encapsulates a key. Key can be either a symmetric key or an asymmetric key.
+ * If it is an asymmetric key, it is used for key exchange.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable Key {
+    /**
+     * If the Key is an asymmetric key, public key should be present.
+     */
+    @nullable PubKey pubKey;
+
+    /**
+     * Arc from the per-boot key to the payload key. The payload key is either the symmetric key
+     * or the private key of an asymmetric key, based on the type of the key being created.
+     * This is marked as optional because there are instances where only the public key is returned,
+     * e.g. `init` method in the key exchange protocol.
+     */
+    @nullable Arc arcFromPBK;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.aidl
new file mode 100644
index 0000000..5483ec5
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+
+/**
+ * One of the two enum variants of the enum type: `PubKey`. This represents the plain public key
+ * material encoded as a COSE_Key.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable PlainPubKey {
+    /* Data is CBOR-encoded according to the `PlainPubKey` CDDL definition in PlainPubKey.cddl */
+    byte[] plainPubKey;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.cddl
new file mode 100644
index 0000000..34b316b
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.cddl
@@ -0,0 +1,24 @@
+;
+; Copyright (C) 2023 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.
+;
+
+; P-256 public key for key exchange.
+PlainPubKey = [ ; COSE_Key [RFC9052 s7]
+    1 : 2,                       ; Key type : EC2
+    3 : -27,                     ; Algorithm : ECDH-SS + HKDF-256
+    -1 : 1,                      ; Curve: P256
+    -2 : bstr,                   ; X coordinate, big-endian
+    -3 : bstr                    ; Y coordinate, big-endian
+]
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/PubKey.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/PubKey.aidl
new file mode 100644
index 0000000..8640871
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/PubKey.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+
+import android.hardware.security.authgraph.PlainPubKey;
+import android.hardware.security.authgraph.SignedPubKey;
+
+/**
+ * The enum type representing the public key of an asymmetric key pair.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+union PubKey {
+    /**
+     * Plain public key material encoded as a COSE_Key.
+     */
+    PlainPubKey plainKey;
+
+    /**
+     * Public key signed with the long term signing key of the party.
+     */
+    SignedPubKey signedKey;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.aidl
new file mode 100644
index 0000000..2fa8b4c
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+
+/**
+ * Signature computed by a party over the session id during authenticated key exchange.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable SessionIdSignature {
+    /* Data is CBOR-encoded according to the `SessionIdSignature` CDDL definition in
+     * SessionIdSignature.cddl */
+    byte[] signature;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.cddl
new file mode 100644
index 0000000..038a0f0
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.cddl
@@ -0,0 +1,33 @@
+;
+; Copyright (C) 2023 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.
+;
+SessionIdSignature = [ ; COSE_Sign1 (untagged) [RFC9052 s4.2]
+    protected: bstr .cbor SessionIdSignatureProtected,
+    unprotected: {},
+    payload: nil,       ; session ID payload to be transported separately
+    signature: bstr     ; PureEd25519(privateKey, SessionIdSignatureSigStruct) /
+                        ; ECDSA(privateKey, SessionIdSignatureSigStruct)
+]
+
+SessionIdSignatureProtected = {
+    1 : AlgorithmEdDSA / AlgorithmES256,
+}
+
+SessionIdSignatureSigStruct = [ ; Sig_structure for SessionIdSignature [ RFC9052 s4.4]
+    context: "Signature1",
+    protected: bstr SessionIdSignatureProtected,
+    external_aad: bstr .size 0,
+    payload: bstr,       ; session ID payload provided separately
+]
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl
new file mode 100644
index 0000000..ef49a1a
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+
+import android.hardware.security.authgraph.Arc;
+import android.hardware.security.authgraph.SessionIdSignature;
+
+/**
+ * Session information returned as part of authenticated key exchange.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable SessionInfo {
+    /**
+     * The arcs that encrypt the two derived symmetric encryption keys (for two-way communication)
+     * from the party's per-boot key.
+     */
+    Arc[2] sharedKeys;
+
+    /**
+     * The value of the session id computed by the two parties during the authenticate key
+     * exchange. Apart from the usage of the session id by the two peers, session id is also useful
+     * to verify (by a third party) that the key exchange was successful.
+     */
+    byte[] sessionId;
+
+    /**
+     * The signature over the session id, created by the party who computed the session id.
+     *
+     * If there is one or more `DiceChainEntry` in the `ExplicitKeyDiceCertChain` of the party's
+     * identity, the signature is verified with the public key in the leaf of the chain of
+     * DiceChainEntries (i.e the public key in the last of the array of DiceChainEntries).
+     * Otherwise, the signature is verified with the `DiceCertChainInitialPayload`.
+     */
+    SessionIdSignature signature;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl
new file mode 100644
index 0000000..c630d91
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+
+import android.hardware.security.authgraph.Arc;
+import android.hardware.security.authgraph.Identity;
+import android.hardware.security.authgraph.Key;
+
+/**
+ * Session initiation information returned as part of authenticated key exchange.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable SessionInitiationInfo {
+    /**
+     * An ephemeral EC key created for the ECDH process.
+     */
+    Key key;
+
+    /**
+     * The identity of the party who created the Diffie-Hellman key exchange key.
+     */
+    Identity identity;
+
+    /**
+     * Nonce value specific to this session. The nonce serves three purposes:
+     * 1. freshness of key exchange
+     * 2. creating a session id (a publicly known value related to the exchanged keys)
+     * 3. usage as salt into the HKDF-EXTRACT function during key derivation from the shared DH key
+     */
+    byte[] nonce;
+
+    /**
+     * The protocol version (i.e. AIDL version) - This is used to prevent version downgrade attacks
+     * as follows:
+     * 1. In `create`, the source advertises the latest protocol version supported by the source,
+     *    which is given as input to the `init` call on the sink in the input parameter:
+     *    `peerVersion`.
+     * 2. In `init`, the sink includes the `peerVersion` in the inputs to the derivation of the
+     *    shared keys. Then the sink returns the latest protocol version supported by the sink,
+     *    which is given as input to the `finish` call on the source in the input parameter:
+     *    `peerVersion`.
+     * 3. In `finish`, the source first checks whether the sink's version is equal or less than the
+     *    source's version and includes in the source's version in the inputs to the derivation of
+     *    the shared keys.
+     * Analysis: if an attacker-in-the-middle wanted the two parties to use an older (vulnerable)
+     * version of the protocol, they can invoke `init` with a version that is lower than the version
+     * advertised by the source in `create`. However, since both parties include the source's
+     * version in the inputs to the derivation of the shared keys, the two parties won't end up with
+     * the same shared keys in the presence of such an attack. This is detected when checking the
+     * signature on the session id in `finish`, at which point the protocol aborts. Therefore,
+     * an attacker cannot successfully launch a version downgrade attack on this protocol.
+     */
+    int version;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.aidl
new file mode 100644
index 0000000..72ee219
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 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.security.authgraph;
+
+/**
+ * One of the two enum variants of the enum type: `PubKey`. This represents the public key signed
+ * with the long term signing key of the party.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable SignedPubKey {
+    /* Data is CBOR-encoded according to the `SignedPubKey` CDDL definition in SignedPubKey.cddl */
+    byte[] signedPubKey;
+}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.cddl
new file mode 100644
index 0000000..f23a492
--- /dev/null
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.cddl
@@ -0,0 +1,41 @@
+;
+; Copyright (C) 2023 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.
+;
+SignedPubKey = [ ; COSE_Sign1 (untagged) [RFC9052 s4.2]
+    protected: bstr .cbor SignedPubKeyProtected,
+    unprotected: {},
+    payload: bstr .cbor PlainPubKey,
+    signature: bstr     ; PureEd25519(privateKey, SignedPubKeySigStruct) /
+                        ; ECDSA(privateKey, SignedPubKeySigStruct)
+]
+
+SignedPubKeyProtected = {
+           1 : AlgorithmEdDSA / AlgorithmES256,
+    ? -70011 : Identity,        ; the party who performs the signing operation adds its own
+                                ; identity to the protected headers.
+}
+
+SignedPubKeySigStruct = [ ; Sig_structure for SignedPubKey [ RFC9052 s4.4]
+    context: "Signature1",
+    protected: bstr SignedPubKeyProtected,
+    external_aad: bstr .size 0,
+    payload: bstr .cbor PlainPubKey,
+]
+
+AlgorithmES256 = -7              ; [RFC9053 s2.1]
+AlgorithmEdDSA = -8              ; [RFC9053 s2.2]
+
+; INCLUDE PlainPubKey.cddl for: PlainPubKey
+; INCLUDE Identity.cddl for: Identity
\ No newline at end of file
diff --git a/security/authgraph/aidl/vts/functional/Android.bp b/security/authgraph/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..fc13759
--- /dev/null
+++ b/security/authgraph/aidl/vts/functional/Android.bp
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2023 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_test {
+    name: "VtsAidlAuthGraphSessionTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "authgraph_use_latest_hal_aidl_ndk_static",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+    ],
+    srcs: [
+        "AuthGraphSessionTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libcrypto",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/security/authgraph/aidl/vts/functional/AuthGraphSessionTest.cpp b/security/authgraph/aidl/vts/functional/AuthGraphSessionTest.cpp
new file mode 100644
index 0000000..d9dea77
--- /dev/null
+++ b/security/authgraph/aidl/vts/functional/AuthGraphSessionTest.cpp
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2023 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 "authgraph_session_test"
+#include <android-base/logging.h>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/security/authgraph/Error.h>
+#include <aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.h>
+#include <android/binder_manager.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+#include <vector>
+
+namespace aidl::android::hardware::security::authgraph::test {
+using ::aidl::android::hardware::security::authgraph::Error;
+
+namespace {
+
+// Check that the signature in the encoded COSE_Sign1 data is correct, and that the payload matches.
+// TODO: maybe drop separate payload, and extract it from cose_sign1.payload (and return it).
+void CheckSignature(std::vector<uint8_t>& /*pub_cose_key*/, std::vector<uint8_t>& /*payload*/,
+                    std::vector<uint8_t>& /*cose_sign1*/) {
+    // TODO: implement me
+}
+
+void CheckSignature(std::vector<uint8_t>& pub_cose_key, std::vector<uint8_t>& payload,
+                    SessionIdSignature& signature) {
+    return CheckSignature(pub_cose_key, payload, signature.signature);
+}
+
+std::vector<uint8_t> SigningKeyFromIdentity(const Identity& identity) {
+    // TODO: This is a CBOR-encoded `Identity` which currently happens to be a COSE_Key with the
+    // pubkey This will change in future.
+    return identity.identity;
+}
+
+}  // namespace
+
+class AuthGraphSessionTest : public ::testing::TestWithParam<std::string> {
+  public:
+    enum ErrorType { AIDL_ERROR, BINDER_ERROR };
+
+    union ErrorValue {
+        Error aidl_error;
+        int32_t binder_error;
+    };
+
+    struct ReturnedError {
+        ErrorType err_type;
+        ErrorValue err_val;
+
+        friend bool operator==(const ReturnedError& lhs, const ReturnedError& rhs) {
+            return lhs.err_type == rhs.err_type;
+            switch (lhs.err_type) {
+                case ErrorType::AIDL_ERROR:
+                    return lhs.err_val.aidl_error == rhs.err_val.aidl_error;
+                case ErrorType::BINDER_ERROR:
+                    return lhs.err_val.binder_error == rhs.err_val.binder_error;
+            }
+        }
+    };
+
+    const ReturnedError OK = {.err_type = ErrorType::AIDL_ERROR, .err_val.aidl_error = Error::OK};
+
+    ReturnedError GetReturnError(const ::ndk::ScopedAStatus& result) {
+        if (result.isOk()) {
+            return OK;
+        }
+        int32_t exception_code = result.getExceptionCode();
+        int32_t error_code = result.getServiceSpecificError();
+        if (exception_code == EX_SERVICE_SPECIFIC && error_code != 0) {
+            ReturnedError re = {.err_type = ErrorType::AIDL_ERROR,
+                                .err_val.aidl_error = static_cast<Error>(error_code)};
+            return re;
+        }
+        ReturnedError re = {.err_type = ErrorType::BINDER_ERROR,
+                            .err_val.binder_error = exception_code};
+        return re;
+    }
+
+    // Build the parameters for the VTS test by enumerating the available HAL instances
+    static std::vector<std::string> build_params() {
+        auto params = ::android::getAidlHalInstanceNames(IAuthGraphKeyExchange::descriptor);
+        return params;
+    }
+
+    void SetUp() override {
+        ASSERT_TRUE(AServiceManager_isDeclared(GetParam().c_str()))
+                << "No instance declared for " << GetParam();
+        ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+        authNode_ = IAuthGraphKeyExchange::fromBinder(binder);
+        ASSERT_NE(authNode_, nullptr) << "Failed to get Binder reference for " << GetParam();
+    }
+
+    void TearDown() override {}
+
+  protected:
+    std::shared_ptr<IAuthGraphKeyExchange> authNode_;
+};
+
+TEST_P(AuthGraphSessionTest, Mainline) {
+    std::shared_ptr<IAuthGraphKeyExchange> source = authNode_;
+    std::shared_ptr<IAuthGraphKeyExchange> sink = authNode_;
+
+    // Step 1: create an ephemeral ECDH key at the source.
+    SessionInitiationInfo source_init_info;
+    ASSERT_EQ(OK, GetReturnError(source->create(&source_init_info)));
+    ASSERT_TRUE(source_init_info.key.pubKey.has_value());
+    ASSERT_TRUE(source_init_info.key.arcFromPBK.has_value());
+
+    // Step 2: pass the source's ECDH public key and other session info to the sink.
+    KeInitResult init_result;
+    ASSERT_EQ(OK, GetReturnError(sink->init(source_init_info.key.pubKey.value(),
+                                            source_init_info.identity, source_init_info.nonce,
+                                            source_init_info.version, &init_result)));
+    SessionInitiationInfo sink_init_info = init_result.sessionInitiationInfo;
+    ASSERT_TRUE(sink_init_info.key.pubKey.has_value());
+    // The sink_init_info.arcFromPBK need not be populated, as the ephemeral key agreement
+    // key is no longer needed.
+
+    SessionInfo sink_info = init_result.sessionInfo;
+    ASSERT_EQ((int)sink_info.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
+    ASSERT_GT((int)sink_info.sessionId.size(), 0) << "Expect non-empty session ID from sink";
+    std::vector<uint8_t> sink_signing_key = SigningKeyFromIdentity(sink_init_info.identity);
+    CheckSignature(sink_signing_key, sink_info.sessionId, sink_info.signature);
+
+    // Step 3: pass the sink's ECDH public key and other session info to the source, so it can
+    // calculate the same pair of symmetric keys.
+    SessionInfo source_info;
+    ASSERT_EQ(OK, GetReturnError(source->finish(sink_init_info.key.pubKey.value(),
+                                                sink_init_info.identity, sink_info.signature,
+                                                sink_init_info.nonce, sink_init_info.version,
+                                                source_init_info.key, &source_info)));
+    ASSERT_EQ((int)source_info.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
+    ASSERT_GT((int)source_info.sessionId.size(), 0) << "Expect non-empty session ID from source";
+    std::vector<uint8_t> source_signing_key = SigningKeyFromIdentity(source_init_info.identity);
+    CheckSignature(source_signing_key, source_info.sessionId, source_info.signature);
+
+    // Both ends should agree on the session ID.
+    ASSERT_EQ(source_info.sessionId, sink_info.sessionId);
+
+    // Step 4: pass the source's session ID info back to the sink, so it can check it and
+    // update the symmetric keys so they're marked as authentication complete.
+    std::array<Arc, 2> auth_complete_result;
+    ASSERT_EQ(OK, GetReturnError(sink->authenticationComplete(
+                          source_info.signature, sink_info.sharedKeys, &auth_complete_result)));
+    ASSERT_EQ((int)auth_complete_result.size(), 2)
+            << "Expect two symmetric keys from authComplete()";
+    sink_info.sharedKeys = auth_complete_result;
+
+    // At this point the sink and source have agreed on the same pair of symmetric keys,
+    // encoded as `sink_info.sharedKeys` and `source_info.sharedKeys`.
+}
+
+TEST_P(AuthGraphSessionTest, ParallelSink) {
+    std::shared_ptr<IAuthGraphKeyExchange> source = authNode_;
+    std::shared_ptr<IAuthGraphKeyExchange> sink1 = authNode_;
+    std::shared_ptr<IAuthGraphKeyExchange> sink2 = authNode_;
+
+    // Step 1: create ephemeral ECDH keys at the source.
+    SessionInitiationInfo source_init1_info;
+    ASSERT_EQ(OK, GetReturnError(source->create(&source_init1_info)));
+    ASSERT_TRUE(source_init1_info.key.pubKey.has_value());
+    ASSERT_TRUE(source_init1_info.key.arcFromPBK.has_value());
+    SessionInitiationInfo source_init2_info;
+    ASSERT_EQ(OK, GetReturnError(source->create(&source_init2_info)));
+    ASSERT_TRUE(source_init2_info.key.pubKey.has_value());
+    ASSERT_TRUE(source_init2_info.key.arcFromPBK.has_value());
+
+    // Step 2: pass the source's ECDH public keys and other session info to the sinks.
+    KeInitResult init1_result;
+    ASSERT_EQ(OK, GetReturnError(sink1->init(source_init1_info.key.pubKey.value(),
+                                             source_init1_info.identity, source_init1_info.nonce,
+                                             source_init1_info.version, &init1_result)));
+    SessionInitiationInfo sink1_init_info = init1_result.sessionInitiationInfo;
+    ASSERT_TRUE(sink1_init_info.key.pubKey.has_value());
+
+    SessionInfo sink1_info = init1_result.sessionInfo;
+    ASSERT_EQ((int)sink1_info.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
+    ASSERT_GT((int)sink1_info.sessionId.size(), 0) << "Expect non-empty session ID from sink";
+    std::vector<uint8_t> sink1_signing_key = SigningKeyFromIdentity(sink1_init_info.identity);
+    CheckSignature(sink1_signing_key, sink1_info.sessionId, sink1_info.signature);
+    KeInitResult init2_result;
+    ASSERT_EQ(OK, GetReturnError(sink2->init(source_init2_info.key.pubKey.value(),
+                                             source_init2_info.identity, source_init2_info.nonce,
+                                             source_init2_info.version, &init2_result)));
+    SessionInitiationInfo sink2_init_info = init2_result.sessionInitiationInfo;
+    ASSERT_TRUE(sink2_init_info.key.pubKey.has_value());
+
+    SessionInfo sink2_info = init2_result.sessionInfo;
+    ASSERT_EQ((int)sink2_info.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
+    ASSERT_GT((int)sink2_info.sessionId.size(), 0) << "Expect non-empty session ID from sink";
+    std::vector<uint8_t> sink2_signing_key = SigningKeyFromIdentity(sink2_init_info.identity);
+    CheckSignature(sink2_signing_key, sink2_info.sessionId, sink2_info.signature);
+
+    // Step 3: pass each sink's ECDH public key and other session info to the source, so it can
+    // calculate the same pair of symmetric keys.
+    SessionInfo source_info1;
+    ASSERT_EQ(OK, GetReturnError(source->finish(sink1_init_info.key.pubKey.value(),
+                                                sink1_init_info.identity, sink1_info.signature,
+                                                sink1_init_info.nonce, sink1_init_info.version,
+                                                source_init1_info.key, &source_info1)));
+    ASSERT_EQ((int)source_info1.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
+    ASSERT_GT((int)source_info1.sessionId.size(), 0) << "Expect non-empty session ID from source";
+    std::vector<uint8_t> source_signing_key1 = SigningKeyFromIdentity(source_init1_info.identity);
+    CheckSignature(source_signing_key1, source_info1.sessionId, source_info1.signature);
+    SessionInfo source_info2;
+    ASSERT_EQ(OK, GetReturnError(source->finish(sink2_init_info.key.pubKey.value(),
+                                                sink2_init_info.identity, sink2_info.signature,
+                                                sink2_init_info.nonce, sink2_init_info.version,
+                                                source_init2_info.key, &source_info2)));
+    ASSERT_EQ((int)source_info2.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
+    ASSERT_GT((int)source_info2.sessionId.size(), 0) << "Expect non-empty session ID from source";
+    std::vector<uint8_t> source_signing_key2 = SigningKeyFromIdentity(source_init2_info.identity);
+    CheckSignature(source_signing_key2, source_info2.sessionId, source_info2.signature);
+
+    // Both ends should agree on the session ID.
+    ASSERT_EQ(source_info1.sessionId, sink1_info.sessionId);
+    ASSERT_EQ(source_info2.sessionId, sink2_info.sessionId);
+
+    // Step 4: pass the source's session ID info back to the sink, so it can check it and
+    // update the symmetric keys so they're marked as authentication complete.
+    std::array<Arc, 2> auth_complete_result1;
+    ASSERT_EQ(OK, GetReturnError(sink1->authenticationComplete(
+                          source_info1.signature, sink1_info.sharedKeys, &auth_complete_result1)));
+    ASSERT_EQ((int)auth_complete_result1.size(), 2)
+            << "Expect two symmetric keys from authComplete()";
+    sink1_info.sharedKeys = auth_complete_result1;
+    std::array<Arc, 2> auth_complete_result2;
+    ASSERT_EQ(OK, GetReturnError(sink2->authenticationComplete(
+                          source_info2.signature, sink2_info.sharedKeys, &auth_complete_result2)));
+    ASSERT_EQ((int)auth_complete_result2.size(), 2)
+            << "Expect two symmetric keys from authComplete()";
+    sink2_info.sharedKeys = auth_complete_result2;
+}
+
+TEST_P(AuthGraphSessionTest, ParallelSource) {
+    std::shared_ptr<IAuthGraphKeyExchange> source1 = authNode_;
+    std::shared_ptr<IAuthGraphKeyExchange> source2 = authNode_;
+    std::shared_ptr<IAuthGraphKeyExchange> sink = authNode_;
+
+    // Step 1: create an ephemeral ECDH key at each of the sources.
+    SessionInitiationInfo source1_init_info;
+    ASSERT_EQ(OK, GetReturnError(source1->create(&source1_init_info)));
+    ASSERT_TRUE(source1_init_info.key.pubKey.has_value());
+    ASSERT_TRUE(source1_init_info.key.arcFromPBK.has_value());
+    SessionInitiationInfo source2_init_info;
+    ASSERT_EQ(OK, GetReturnError(source1->create(&source2_init_info)));
+    ASSERT_TRUE(source2_init_info.key.pubKey.has_value());
+    ASSERT_TRUE(source2_init_info.key.arcFromPBK.has_value());
+
+    // Step 2: pass each source's ECDH public key and other session info to the sink.
+    KeInitResult init1_result;
+    ASSERT_EQ(OK, GetReturnError(sink->init(source1_init_info.key.pubKey.value(),
+                                            source1_init_info.identity, source1_init_info.nonce,
+                                            source1_init_info.version, &init1_result)));
+    SessionInitiationInfo sink_init1_info = init1_result.sessionInitiationInfo;
+    ASSERT_TRUE(sink_init1_info.key.pubKey.has_value());
+
+    SessionInfo sink_info1 = init1_result.sessionInfo;
+    ASSERT_EQ((int)sink_info1.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
+    ASSERT_GT((int)sink_info1.sessionId.size(), 0) << "Expect non-empty session ID from sink";
+    std::vector<uint8_t> sink_signing_key1 = SigningKeyFromIdentity(sink_init1_info.identity);
+    CheckSignature(sink_signing_key1, sink_info1.sessionId, sink_info1.signature);
+
+    KeInitResult init2_result;
+    ASSERT_EQ(OK, GetReturnError(sink->init(source2_init_info.key.pubKey.value(),
+                                            source2_init_info.identity, source2_init_info.nonce,
+                                            source2_init_info.version, &init2_result)));
+    SessionInitiationInfo sink_init2_info = init2_result.sessionInitiationInfo;
+    ASSERT_TRUE(sink_init2_info.key.pubKey.has_value());
+
+    SessionInfo sink_info2 = init2_result.sessionInfo;
+    ASSERT_EQ((int)sink_info2.sharedKeys.size(), 2) << "Expect two symmetric keys from init()";
+    ASSERT_GT((int)sink_info2.sessionId.size(), 0) << "Expect non-empty session ID from sink";
+    std::vector<uint8_t> sink_signing_key2 = SigningKeyFromIdentity(sink_init2_info.identity);
+    CheckSignature(sink_signing_key2, sink_info2.sessionId, sink_info2.signature);
+
+    // Step 3: pass the sink's ECDH public keys and other session info to the each of the sources.
+    SessionInfo source1_info;
+    ASSERT_EQ(OK, GetReturnError(source1->finish(sink_init1_info.key.pubKey.value(),
+                                                 sink_init1_info.identity, sink_info1.signature,
+                                                 sink_init1_info.nonce, sink_init1_info.version,
+                                                 source1_init_info.key, &source1_info)));
+    ASSERT_EQ((int)source1_info.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
+    ASSERT_GT((int)source1_info.sessionId.size(), 0) << "Expect non-empty session ID from source";
+    std::vector<uint8_t> source1_signing_key = SigningKeyFromIdentity(source1_init_info.identity);
+    CheckSignature(source1_signing_key, source1_info.sessionId, source1_info.signature);
+
+    SessionInfo source2_info;
+    ASSERT_EQ(OK, GetReturnError(source2->finish(sink_init2_info.key.pubKey.value(),
+                                                 sink_init2_info.identity, sink_info2.signature,
+                                                 sink_init2_info.nonce, sink_init2_info.version,
+                                                 source2_init_info.key, &source2_info)));
+    ASSERT_EQ((int)source2_info.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()";
+    ASSERT_GT((int)source2_info.sessionId.size(), 0) << "Expect non-empty session ID from source";
+    std::vector<uint8_t> source2_signing_key = SigningKeyFromIdentity(source2_init_info.identity);
+    CheckSignature(source2_signing_key, source2_info.sessionId, source2_info.signature);
+
+    // Both ends should agree on the session ID.
+    ASSERT_EQ(source1_info.sessionId, sink_info1.sessionId);
+    ASSERT_EQ(source2_info.sessionId, sink_info2.sessionId);
+
+    // Step 4: pass the each source's session ID info back to the sink, so it can check it and
+    // update the symmetric keys so they're marked as authentication complete.
+    std::array<Arc, 2> auth_complete_result1;
+    ASSERT_EQ(OK, GetReturnError(sink->authenticationComplete(
+                          source1_info.signature, sink_info1.sharedKeys, &auth_complete_result1)));
+    ASSERT_EQ((int)auth_complete_result1.size(), 2)
+            << "Expect two symmetric keys from authComplete()";
+    sink_info1.sharedKeys = auth_complete_result1;
+    std::array<Arc, 2> auth_complete_result2;
+    ASSERT_EQ(OK, GetReturnError(sink->authenticationComplete(
+                          source2_info.signature, sink_info2.sharedKeys, &auth_complete_result2)));
+    ASSERT_EQ((int)auth_complete_result2.size(), 2)
+            << "Expect two symmetric keys from authComplete()";
+    sink_info2.sharedKeys = auth_complete_result2;
+}
+
+TEST_P(AuthGraphSessionTest, FreshNonces) {
+    std::shared_ptr<IAuthGraphKeyExchange> source = authNode_;
+    std::shared_ptr<IAuthGraphKeyExchange> sink = authNode_;
+
+    SessionInitiationInfo source_init_info1;
+    ASSERT_EQ(OK, GetReturnError(source->create(&source_init_info1)));
+    SessionInitiationInfo source_init_info2;
+    ASSERT_EQ(OK, GetReturnError(source->create(&source_init_info2)));
+
+    // Two calls to create() should result in the same identity but different nonce values.
+    ASSERT_EQ(source_init_info1.identity, source_init_info2.identity);
+    ASSERT_NE(source_init_info1.nonce, source_init_info2.nonce);
+    ASSERT_NE(source_init_info1.key.pubKey, source_init_info2.key.pubKey);
+    ASSERT_NE(source_init_info1.key.arcFromPBK, source_init_info2.key.arcFromPBK);
+
+    KeInitResult init_result1;
+    ASSERT_EQ(OK, GetReturnError(sink->init(source_init_info1.key.pubKey.value(),
+                                            source_init_info1.identity, source_init_info1.nonce,
+                                            source_init_info1.version, &init_result1)));
+    KeInitResult init_result2;
+    ASSERT_EQ(OK, GetReturnError(sink->init(source_init_info2.key.pubKey.value(),
+                                            source_init_info2.identity, source_init_info2.nonce,
+                                            source_init_info2.version, &init_result2)));
+
+    // Two calls to init() should result in the same identity buf different nonces and session IDs.
+    ASSERT_EQ(init_result1.sessionInitiationInfo.identity,
+              init_result2.sessionInitiationInfo.identity);
+    ASSERT_NE(init_result1.sessionInitiationInfo.nonce, init_result2.sessionInitiationInfo.nonce);
+    ASSERT_NE(init_result1.sessionInfo.sessionId, init_result2.sessionInfo.sessionId);
+}
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, AuthGraphSessionTest,
+                         testing::ValuesIn(AuthGraphSessionTest::build_params()),
+                         ::android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AuthGraphSessionTest);
+
+}  // namespace aidl::android::hardware::security::authgraph::test
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/security/authgraph/default/Android.bp b/security/authgraph/default/Android.bp
new file mode 100644
index 0000000..9de3bc1
--- /dev/null
+++ b/security/authgraph/default/Android.bp
@@ -0,0 +1,46 @@
+//
+// Copyright (C) 2023 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"],
+}
+
+rust_binary {
+    name: "android.hardware.security.authgraph-service.nonsecure",
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["authgraph.rc"],
+    vintf_fragments: ["authgraph.xml"],
+    defaults: [
+        "authgraph_use_latest_hal_aidl_rust",
+    ],
+    rustlibs: [
+        "libandroid_logger",
+        "libauthgraph_core",
+        "libauthgraph_boringssl",
+        "libauthgraph_hal",
+        "libbinder_rs",
+        "liblibc",
+        "liblog_rust",
+    ],
+    srcs: [
+        "src/main.rs",
+    ],
+}
diff --git a/security/authgraph/default/authgraph.rc b/security/authgraph/default/authgraph.rc
new file mode 100644
index 0000000..0222994
--- /dev/null
+++ b/security/authgraph/default/authgraph.rc
@@ -0,0 +1,5 @@
+service vendor.authgraph /vendor/bin/hw/android.hardware.security.authgraph-service.nonsecure
+    interface aidl android.hardware.security.authgraph.IAuthGraph/nonsecure
+    class hal
+    user nobody
+    group nobody
diff --git a/security/authgraph/default/authgraph.xml b/security/authgraph/default/authgraph.xml
new file mode 100644
index 0000000..9529a0a
--- /dev/null
+++ b/security/authgraph/default/authgraph.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.security.authgraph</name>
+        <version>1</version>
+        <interface>
+            <name>IAuthGraphKeyExchange</name>
+            <instance>nonsecure</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/security/authgraph/default/src/main.rs b/security/authgraph/default/src/main.rs
new file mode 100644
index 0000000..2112e58
--- /dev/null
+++ b/security/authgraph/default/src/main.rs
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+//! Default implementation of the AuthGraph key exchange HAL.
+//!
+//! This implementation of the HAL is only intended to allow testing and policy compliance.  A real
+//! implementation of the AuthGraph HAL would be implemented in a secure environment, and would not
+//! be independently registered with service manager (a secure component that uses AuthGraph would
+//! expose an entrypoint that allowed retrieval of the specific IAuthGraphKeyExchange instance that
+//! is correlated with the component).
+
+use android_hardware_security_authgraph::aidl::android::hardware::security::authgraph::{
+    Arc::Arc, IAuthGraphKeyExchange::BnAuthGraphKeyExchange,
+    IAuthGraphKeyExchange::IAuthGraphKeyExchange, Identity::Identity, KeInitResult::KeInitResult,
+    Key::Key, PubKey::PubKey, SessionIdSignature::SessionIdSignature, SessionInfo::SessionInfo,
+    SessionInitiationInfo::SessionInitiationInfo,
+};
+use authgraph_boringssl as boring;
+use authgraph_core::{key::MillisecondsSinceEpoch, keyexchange as ke, traits};
+use authgraph_hal::{err_to_binder, Innto, TryInnto};
+use log::{error, info};
+use std::ffi::CString;
+use std::sync::Mutex;
+
+static SERVICE_NAME: &str = "android.hardware.security.authgraph.IAuthGraphKeyExchange";
+static SERVICE_INSTANCE: &str = "nonsecure";
+
+/// Local error type for failures in the HAL service.
+#[derive(Debug, Clone)]
+struct HalServiceError(String);
+
+impl From<String> for HalServiceError {
+    fn from(s: String) -> Self {
+        Self(s)
+    }
+}
+
+fn main() {
+    if let Err(e) = inner_main() {
+        panic!("HAL service failed: {:?}", e);
+    }
+}
+
+fn inner_main() -> Result<(), HalServiceError> {
+    // Initialize Android logging.
+    android_logger::init_once(
+        android_logger::Config::default()
+            .with_tag("authgraph-hal-nonsecure")
+            .with_min_level(log::Level::Info)
+            .with_log_id(android_logger::LogId::System),
+    );
+    // Redirect panic messages to logcat.
+    std::panic::set_hook(Box::new(|panic_info| {
+        error!("{}", panic_info);
+    }));
+
+    info!("Insecure AuthGraph key exchange HAL service is starting.");
+
+    info!("Starting thread pool now.");
+    binder::ProcessState::start_thread_pool();
+
+    // Register the service
+    let service = AuthGraphService::new_as_binder();
+    let service_name = format!("{}/{}", SERVICE_NAME, SERVICE_INSTANCE);
+    binder::add_service(&service_name, service.as_binder()).map_err(|e| {
+        format!(
+            "Failed to register service {} because of {:?}.",
+            service_name, e
+        )
+    })?;
+
+    info!("Successfully registered AuthGraph HAL services.");
+    binder::ProcessState::join_thread_pool();
+    info!("AuthGraph HAL service is terminating."); // should not reach here
+    Ok(())
+}
+
+/// Non-secure implementation of the AuthGraph key exchange service.
+struct AuthGraphService {
+    imp: Mutex<traits::TraitImpl>,
+}
+
+impl AuthGraphService {
+    /// Create a new instance.
+    fn new() -> Self {
+        Self {
+            imp: Mutex::new(traits::TraitImpl {
+                aes_gcm: Box::new(boring::BoringAes),
+                ecdh: Box::new(boring::BoringEcDh),
+                ecdsa: Box::new(boring::BoringEcDsa),
+                hmac: Box::new(boring::BoringHmac),
+                hkdf: Box::new(boring::BoringHkdf),
+                sha256: Box::new(boring::BoringSha256),
+                rng: Box::new(boring::BoringRng),
+                device: Box::<boring::test_device::AgDevice>::default(),
+                clock: Some(Box::new(StdClock)),
+            }),
+        }
+    }
+
+    /// Create a new instance wrapped in a proxy object.
+    pub fn new_as_binder() -> binder::Strong<dyn IAuthGraphKeyExchange> {
+        BnAuthGraphKeyExchange::new_binder(Self::new(), binder::BinderFeatures::default())
+    }
+}
+
+impl binder::Interface for AuthGraphService {}
+
+/// Extract (and require) an unsigned public key as bytes from a [`PubKey`].
+fn unsigned_pub_key(pub_key: &PubKey) -> binder::Result<&[u8]> {
+    match pub_key {
+        PubKey::PlainKey(key) => Ok(&key.plainPubKey),
+        PubKey::SignedKey(_) => Err(binder::Status::new_exception(
+            binder::ExceptionCode::ILLEGAL_ARGUMENT,
+            Some(&CString::new("expected unsigned public key").unwrap()),
+        )),
+    }
+}
+
+/// This nonsecure implementation of the AuthGraph HAL interface directly calls the AuthGraph
+/// reference implementation library code; a real implementation requires the AuthGraph
+/// code to run in a secure environment, not within Android.
+impl IAuthGraphKeyExchange for AuthGraphService {
+    fn create(&self) -> binder::Result<SessionInitiationInfo> {
+        info!("create()");
+        let mut imp = self.imp.lock().unwrap();
+        let info = ke::create(&mut *imp).map_err(err_to_binder)?;
+        Ok(info.innto())
+    }
+    fn init(
+        &self,
+        peer_pub_key: &PubKey,
+        peer_id: &Identity,
+        peer_nonce: &[u8],
+        peer_version: i32,
+    ) -> binder::Result<KeInitResult> {
+        info!("init(v={peer_version})");
+        let mut imp = self.imp.lock().unwrap();
+        let peer_pub_key = unsigned_pub_key(peer_pub_key)?;
+        let result = ke::init(
+            &mut *imp,
+            peer_pub_key,
+            &peer_id.identity,
+            &peer_nonce,
+            peer_version,
+        )
+        .map_err(err_to_binder)?;
+        Ok(result.innto())
+    }
+
+    fn finish(
+        &self,
+        peer_pub_key: &PubKey,
+        peer_id: &Identity,
+        peer_signature: &SessionIdSignature,
+        peer_nonce: &[u8],
+        peer_version: i32,
+        own_key: &Key,
+    ) -> binder::Result<SessionInfo> {
+        info!("finish(v={peer_version})");
+        let mut imp = self.imp.lock().unwrap();
+        let peer_pub_key = unsigned_pub_key(peer_pub_key)?;
+        let own_key: Key = own_key.clone();
+        let own_key: authgraph_core::key::Key = own_key.try_innto()?;
+        let session_info = ke::finish(
+            &mut *imp,
+            peer_pub_key,
+            &peer_id.identity,
+            &peer_signature.signature,
+            &peer_nonce,
+            peer_version,
+            own_key,
+        )
+        .map_err(err_to_binder)?;
+        Ok(session_info.innto())
+    }
+
+    fn authenticationComplete(
+        &self,
+        peer_signature: &SessionIdSignature,
+        shared_keys: &[Arc; 2],
+    ) -> binder::Result<[Arc; 2]> {
+        info!("authComplete()");
+        let mut imp = self.imp.lock().unwrap();
+        let shared_keys = [shared_keys[0].arc.clone(), shared_keys[1].arc.clone()];
+        let arcs = ke::authentication_complete(&mut *imp, &peer_signature.signature, shared_keys)
+            .map_err(err_to_binder)?;
+        Ok(arcs.map(|arc| Arc { arc }))
+    }
+}
+
+/// Monotonic clock.
+#[derive(Default)]
+pub struct StdClock;
+
+impl traits::MonotonicClock for StdClock {
+    fn now(&self) -> authgraph_core::key::MillisecondsSinceEpoch {
+        let mut time = libc::timespec {
+            tv_sec: 0,  // libc::time_t
+            tv_nsec: 0, // libc::c_long
+        };
+        let rc =
+        // Safety: `time` is a valid structure.
+            unsafe { libc::clock_gettime(libc::CLOCK_BOOTTIME, &mut time as *mut libc::timespec) };
+        if rc < 0 {
+            log::warn!("failed to get time!");
+            return MillisecondsSinceEpoch(0);
+        }
+        // The types in `libc::timespec` may be different on different architectures,
+        // so allow conversion to `i64`.
+        #[allow(clippy::unnecessary_cast)]
+        MillisecondsSinceEpoch((time.tv_sec as i64 * 1000) + (time.tv_nsec as i64 / 1000 / 1000))
+    }
+}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index 36f0106..aa7bf28 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -643,6 +643,8 @@
      * Tag::ATTESTATION_CHALLENGE is used to deliver a "challenge" value to the attested key
      * generation/import methods, which must place the value in the KeyDescription SEQUENCE of the
      * attestation extension.
+     * The challenge value may be up to 128 bytes. If the caller provides a bigger challenge,
+     * INVALID_INPUT_LENGTH error should be returned.
      *
      * Must never appear in KeyCharacteristics.
      */
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 3a8a1e8..822770d 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -79,7 +79,8 @@
 typedef KeyMintAidlTestBase::KeyData KeyData;
 // Predicate for testing basic characteristics validity in generation or import.
 bool KeyCharacteristicsBasicallyValid(SecurityLevel secLevel,
-                                      const vector<KeyCharacteristics>& key_characteristics) {
+                                      const vector<KeyCharacteristics>& key_characteristics,
+                                      int32_t aidl_version) {
     if (key_characteristics.empty()) return false;
 
     std::unordered_set<SecurityLevel> levels_seen;
@@ -89,7 +90,12 @@
             return false;
         }
 
-        EXPECT_EQ(count_tag_invalid_entries(entry.authorizations), 0);
+        // There was no test to assert that INVALID tag should not present in authorization list
+        // before Keymint V3, so there are some Keymint implementations where asserting for INVALID
+        // tag fails(b/297306437), hence skipping for Keymint < 3.
+        if (aidl_version >= 3) {
+            EXPECT_EQ(count_tag_invalid_entries(entry.authorizations), 0);
+        }
 
         // Just ignore the SecurityLevel::KEYSTORE as the KM won't do any enforcement on this.
         if (entry.securityLevel == SecurityLevel::KEYSTORE) continue;
@@ -264,7 +270,7 @@
     vendor_patch_level_ = getVendorPatchlevel();
 }
 
-int32_t KeyMintAidlTestBase::AidlVersion() {
+int32_t KeyMintAidlTestBase::AidlVersion() const {
     int32_t version = 0;
     auto status = keymint_->getInterfaceVersion(&version);
     if (!status.isOk()) {
@@ -294,8 +300,8 @@
     KeyCreationResult creationResult;
     Status result = keymint_->generateKey(key_desc.vector_data(), attest_key, &creationResult);
     if (result.isOk()) {
-        EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
-                     creationResult.keyCharacteristics);
+        EXPECT_PRED3(KeyCharacteristicsBasicallyValid, SecLevel(),
+                     creationResult.keyCharacteristics, AidlVersion());
         EXPECT_GT(creationResult.keyBlob.size(), 0);
         *key_blob = std::move(creationResult.keyBlob);
         *key_characteristics = std::move(creationResult.keyCharacteristics);
@@ -367,8 +373,8 @@
                                  {} /* attestationSigningKeyBlob */, &creationResult);
 
     if (result.isOk()) {
-        EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
-                     creationResult.keyCharacteristics);
+        EXPECT_PRED3(KeyCharacteristicsBasicallyValid, SecLevel(),
+                     creationResult.keyCharacteristics, AidlVersion());
         EXPECT_GT(creationResult.keyBlob.size(), 0);
 
         *key_blob = std::move(creationResult.keyBlob);
@@ -411,8 +417,8 @@
             unwrapping_params.vector_data(), password_sid, biometric_sid, &creationResult);
 
     if (result.isOk()) {
-        EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
-                     creationResult.keyCharacteristics);
+        EXPECT_PRED3(KeyCharacteristicsBasicallyValid, SecLevel(),
+                     creationResult.keyCharacteristics, AidlVersion());
         EXPECT_GT(creationResult.keyBlob.size(), 0);
 
         key_blob_ = std::move(creationResult.keyBlob);
@@ -2068,27 +2074,36 @@
     return retval;
 }
 
-void assert_mgf_digests_present_in_key_characteristics(
+void KeyMintAidlTestBase::assert_mgf_digests_present_or_not_in_key_characteristics(
+        std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests,
+        bool is_mgf_digest_expected) const {
+    assert_mgf_digests_present_or_not_in_key_characteristics(
+            key_characteristics_, expected_mgf_digests, is_mgf_digest_expected);
+}
+
+void KeyMintAidlTestBase::assert_mgf_digests_present_or_not_in_key_characteristics(
         const vector<KeyCharacteristics>& key_characteristics,
-        std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests) {
+        std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests,
+        bool is_mgf_digest_expected) const {
+    // There was no test to assert that MGF1 digest was present in generated/imported key
+    // characteristics before Keymint V3, so there are some Keymint implementations where
+    // asserting for MGF1 digest fails(b/297306437), hence skipping for Keymint < 3.
+    if (AidlVersion() < 3) {
+        return;
+    }
     AuthorizationSet auths;
     for (auto& entry : key_characteristics) {
         auths.push_back(AuthorizationSet(entry.authorizations));
     }
     for (auto digest : expected_mgf_digests) {
-        ASSERT_TRUE(auths.Contains(TAG_RSA_OAEP_MGF_DIGEST, digest));
+        if (is_mgf_digest_expected) {
+            ASSERT_TRUE(auths.Contains(TAG_RSA_OAEP_MGF_DIGEST, digest));
+        } else {
+            ASSERT_FALSE(auths.Contains(TAG_RSA_OAEP_MGF_DIGEST, digest));
+        }
     }
 }
 
-bool is_mgf_digest_present(const vector<KeyCharacteristics>& key_characteristics,
-                           android::hardware::security::keymint::Digest expected_mgf_digest) {
-    AuthorizationSet auths;
-    for (auto& entry : key_characteristics) {
-        auths.push_back(AuthorizationSet(entry.authorizations));
-    }
-    return auths.Contains(TAG_RSA_OAEP_MGF_DIGEST, expected_mgf_digest);
-}
-
 namespace {
 
 void check_cose_key(const vector<uint8_t>& data, bool testMode) {
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 9778b3d..4fb711c 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -95,7 +95,7 @@
 
     void InitializeKeyMint(std::shared_ptr<IKeyMintDevice> keyMint);
     IKeyMintDevice& keyMint() { return *keymint_; }
-    int32_t AidlVersion();
+    int32_t AidlVersion() const;
     uint32_t os_version() { return os_version_; }
     uint32_t os_patch_level() { return os_patch_level_; }
     uint32_t vendor_patch_level() { return vendor_patch_level_; }
@@ -373,6 +373,15 @@
     bool shouldSkipAttestKeyTest(void) const;
     void skipAttestKeyTest(void) const;
 
+    void assert_mgf_digests_present_or_not_in_key_characteristics(
+            const vector<KeyCharacteristics>& key_characteristics,
+            std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests,
+            bool is_mgf_digest_expected) const;
+
+    void assert_mgf_digests_present_or_not_in_key_characteristics(
+            std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests,
+            bool is_mgf_digest_expected) const;
+
   protected:
     std::shared_ptr<IKeyMintDevice> keymint_;
     uint32_t os_version_;
@@ -430,11 +439,6 @@
 X509_Ptr parse_cert_blob(const vector<uint8_t>& blob);
 ASN1_OCTET_STRING* get_attestation_record(X509* certificate);
 vector<uint8_t> make_name_from_str(const string& name);
-void assert_mgf_digests_present_in_key_characteristics(
-        const vector<KeyCharacteristics>& key_characteristics,
-        std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests);
-bool is_mgf_digest_present(const vector<KeyCharacteristics>& key_characteristics,
-                           android::hardware::security::keymint::Digest expected_mgf_digest);
 void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode,
                         vector<uint8_t>* payload_value);
 void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index de563c4..a8f17dd 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -4743,6 +4743,12 @@
  * should have the correct characteristics.
  */
 TEST_P(ImportKeyTest, RsaOaepMGFDigestSuccess) {
+    // There was no test to assert that MGF1 digest was present in generated/imported key
+    // characteristics before Keymint V3, so there are some Keymint implementations where
+    // this test case fails(b/297306437), hence this test is skipped for Keymint < 3.
+    if (AidlVersion() < 3) {
+        GTEST_SKIP() << "Test not applicable to Keymint < V3";
+    }
     auto mgf_digests = ValidDigests(false /* withNone */, true /* withMD5 */);
     size_t key_size = 2048;
 
@@ -4763,7 +4769,7 @@
     CheckOrigin();
 
     // Make sure explicitly specified mgf-digests exist in key characteristics.
-    assert_mgf_digests_present_in_key_characteristics(key_characteristics_, mgf_digests);
+    assert_mgf_digests_present_or_not_in_key_characteristics(mgf_digests, true);
 
     string message = "Hello";
 
@@ -4827,8 +4833,9 @@
     CheckCryptoParam(TAG_PADDING, PaddingMode::RSA_OAEP);
     CheckOrigin();
 
+    vector defaultDigest = {Digest::SHA1};
     // Make sure default mgf-digest (SHA1) is not included in Key characteristics.
-    ASSERT_FALSE(is_mgf_digest_present(key_characteristics_, Digest::SHA1));
+    assert_mgf_digests_present_or_not_in_key_characteristics(defaultDigest, false);
 }
 
 INSTANTIATE_KEYMINT_AIDL_TEST(ImportKeyTest);
@@ -5256,7 +5263,7 @@
  */
 TEST_P(EncryptionOperationsTest, RsaOaepSuccess) {
     auto digests = ValidDigests(false /* withNone */, true /* withMD5 */);
-    auto mgf_digest = Digest::SHA1;
+    auto mgf_digest = vector{Digest::SHA1};
 
     size_t key_size = 2048;  // Need largish key for SHA-512 test.
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@@ -5264,11 +5271,11 @@
                                                  .RsaEncryptionKey(key_size, 65537)
                                                  .Padding(PaddingMode::RSA_OAEP)
                                                  .Digest(digests)
-                                                 .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+                                                 .OaepMGFDigest(mgf_digest)
                                                  .SetDefaultValidity()));
 
     // Make sure explicitly specified mgf-digest exist in key characteristics.
-    ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+    assert_mgf_digests_present_or_not_in_key_characteristics(mgf_digest, true);
 
     string message = "Hello";
 
@@ -5393,21 +5400,21 @@
                                                  .Padding(PaddingMode::RSA_OAEP)
                                                  .Digest(Digest::SHA_2_256)
                                                  .SetDefaultValidity()));
+    if (AidlVersion() >= 3) {
+        std::vector<Digest> mgf1DigestsInAuths;
+        mgf1DigestsInAuths.reserve(digests.size());
+        const auto& hw_auths = SecLevelAuthorizations(key_characteristics_);
+        std::for_each(hw_auths.begin(), hw_auths.end(), [&](auto& param) {
+            if (param.tag == Tag::RSA_OAEP_MGF_DIGEST) {
+                KeyParameterValue value = param.value;
+                mgf1DigestsInAuths.push_back(param.value.template get<KeyParameterValue::digest>());
+            }
+        });
 
-    std::vector<Digest> mgf1DigestsInAuths;
-    mgf1DigestsInAuths.reserve(digests.size());
-    const auto& hw_auths = SecLevelAuthorizations(key_characteristics_);
-    std::for_each(hw_auths.begin(), hw_auths.end(), [&](auto& param) {
-        if (param.tag == Tag::RSA_OAEP_MGF_DIGEST) {
-            KeyParameterValue value = param.value;
-            mgf1DigestsInAuths.push_back(param.value.template get<KeyParameterValue::digest>());
-        }
-    });
-
-    std::sort(digests.begin(), digests.end());
-    std::sort(mgf1DigestsInAuths.begin(), mgf1DigestsInAuths.end());
-    EXPECT_EQ(digests, mgf1DigestsInAuths);
-
+        std::sort(digests.begin(), digests.end());
+        std::sort(mgf1DigestsInAuths.begin(), mgf1DigestsInAuths.end());
+        EXPECT_EQ(digests, mgf1DigestsInAuths);
+    }
     string message = "Hello";
 
     for (auto digest : digests) {
@@ -5462,8 +5469,9 @@
                                                  .Digest(Digest::SHA_2_256)
                                                  .SetDefaultValidity()));
 
+    vector defaultDigest = vector{Digest::SHA1};
     // Make sure default mgf-digest (SHA1) is not included in Key characteristics.
-    ASSERT_FALSE(is_mgf_digest_present(key_characteristics_, Digest::SHA1));
+    assert_mgf_digests_present_or_not_in_key_characteristics(defaultDigest, false);
 
     // Do local RSA encryption using the default MGF digest of SHA-1.
     string message = "Hello";
@@ -5499,19 +5507,20 @@
  */
 TEST_P(EncryptionOperationsTest, RsaOaepMGFDigestDefaultFail) {
     size_t key_size = 2048;
-    auto mgf_digest = Digest::SHA_2_256;
+    auto mgf_digest = vector{Digest::SHA_2_256};
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                 .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+                                                 .OaepMGFDigest(mgf_digest)
                                                  .RsaEncryptionKey(key_size, 65537)
                                                  .Padding(PaddingMode::RSA_OAEP)
                                                  .Digest(Digest::SHA_2_256)
                                                  .SetDefaultValidity()));
 
     // Make sure explicitly specified mgf-digest exist in key characteristics.
-    ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+    assert_mgf_digests_present_or_not_in_key_characteristics(mgf_digest, true);
+    vector defaultDigest = vector{Digest::SHA1};
     // Make sure default mgf-digest is not included in key characteristics.
-    ASSERT_FALSE(is_mgf_digest_present(key_characteristics_, Digest::SHA1));
+    assert_mgf_digests_present_or_not_in_key_characteristics(defaultDigest, false);
 
     // Do local RSA encryption using the default MGF digest of SHA-1.
     string message = "Hello";
@@ -5535,16 +5544,17 @@
  * with incompatible MGF digest.
  */
 TEST_P(EncryptionOperationsTest, RsaOaepWithMGFIncompatibleDigest) {
-    auto mgf_digest = Digest::SHA_2_256;
+    auto mgf_digest = vector{Digest::SHA_2_256};
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                 .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+                                                 .OaepMGFDigest(mgf_digest)
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
                                                  .RsaEncryptionKey(2048, 65537)
                                                  .Padding(PaddingMode::RSA_OAEP)
                                                  .Digest(Digest::SHA_2_256)
                                                  .SetDefaultValidity()));
+
     // Make sure explicitly specified mgf-digest exist in key characteristics.
-    ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+    assert_mgf_digests_present_or_not_in_key_characteristics(mgf_digest, true);
 
     string message = "Hello World!";
 
@@ -5562,16 +5572,17 @@
  * with unsupported MGF digest.
  */
 TEST_P(EncryptionOperationsTest, RsaOaepWithMGFUnsupportedDigest) {
-    auto mgf_digest = Digest::SHA_2_256;
+    auto mgf_digest = vector{Digest::SHA_2_256};
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                 .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+                                                 .OaepMGFDigest(mgf_digest)
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
                                                  .RsaEncryptionKey(2048, 65537)
                                                  .Padding(PaddingMode::RSA_OAEP)
                                                  .Digest(Digest::SHA_2_256)
                                                  .SetDefaultValidity()));
+
     // Make sure explicitly specified mgf-digest exist in key characteristics.
-    ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+    assert_mgf_digests_present_or_not_in_key_characteristics(mgf_digest, true);
 
     string message = "Hello World!";
 
diff --git a/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
index 15b0442..61404d4 100644
--- a/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
+++ b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
@@ -101,17 +101,19 @@
     -4670545 : bstr,                         ; Code Hash
     ? -4670546 : bstr,                       ; Code Descriptor
     -4670547 : bstr,                         ; Configuration Hash
-    -4670548 : bstr .cbor {                  ; Configuration Descriptor
-        ? -70002 : tstr,                         ; Component name
-        ? -70003 : int / tstr,                   ; Component version
-        ? -70004 : null,                         ; Resettable
-        ? -70005 : uint,                         ; Security version
-    },
+    -4670548 : bstr .cbor ConfigurationDescriptor,
     -4670549 : bstr,                         ; Authority Hash
     ? -4670550 : bstr,                       ; Authority Descriptor
     -4670551 : bstr,                         ; Mode
 }
 
+ConfigurationDescriptor = {                  ; Configuration Descriptor
+    ? -70002 : tstr,                         ; Component name
+    ? -70003 : int / tstr,                   ; Component version
+    ? -70004 : null,                         ; Resettable
+    ? -70005 : uint,                         ; Security version
+}
+
 ; Each entry in the DICE chain is a DiceChainEntryPayload signed by the key from the previous
 ; entry in the DICE chain array.
 DiceChainEntry = [                            ; COSE_Sign1 (untagged), [RFC9052 s4.2]
diff --git a/sensors/aidl/default/Android.bp b/sensors/aidl/default/Android.bp
index 16b4d35..384ee97 100644
--- a/sensors/aidl/default/Android.bp
+++ b/sensors/aidl/default/Android.bp
@@ -28,9 +28,11 @@
     srcs: ["sensors-default.rc"],
 }
 
-filegroup {
+prebuilt_etc {
     name: "sensors-default.xml",
-    srcs: ["sensors-default.xml"],
+    src: "sensors-default.xml",
+    sub_dir: "vintf",
+    installable: false,
 }
 
 cc_library_static {
diff --git a/sensors/aidl/default/apex/Android.bp b/sensors/aidl/default/apex/Android.bp
index ceb428b..5482086 100644
--- a/sensors/aidl/default/apex/Android.bp
+++ b/sensors/aidl/default/apex/Android.bp
@@ -2,17 +2,6 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-apex_key {
-    name: "com.android.hardware.sensors.key",
-    public_key: "com.android.hardware.sensors.avbpubkey",
-    private_key: "com.android.hardware.sensors.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.sensors.certificate",
-    certificate: "com.android.hardware.sensors",
-}
-
 genrule {
     name: "com.android.hardware.sensors.rc-gen",
     srcs: [":sensors-default.rc"],
@@ -31,16 +20,16 @@
 apex {
     name: "com.android.hardware.sensors",
     manifest: "apex_manifest.json",
-    key: "com.android.hardware.sensors.key",
-    certificate: ":com.android.hardware.sensors.certificate",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
     file_contexts: "file_contexts",
-    use_vndk_as_stable: true,
     updatable: false,
-    // Install the apex in /vendor/apex
-    soc_specific: true,
+    vendor: true,
+
     binaries: ["android.hardware.sensors-service.example"],
     prebuilts: [
-        "com.android.hardware.sensors.rc",
+        "com.android.hardware.sensors.rc", // init rc
+        "sensors-default.xml", // vintf fragment
         "android.hardware.sensor.ambient_temperature.prebuilt.xml",
         "android.hardware.sensor.barometer.prebuilt.xml",
         "android.hardware.sensor.gyroscope.prebuilt.xml",
@@ -49,5 +38,4 @@
         "android.hardware.sensor.proximity.prebuilt.xml",
         "android.hardware.sensor.relative_humidity.prebuilt.xml",
     ],
-    vintf_fragments: [":sensors-default.xml"],
 }
diff --git a/sensors/aidl/default/apex/file_contexts b/sensors/aidl/default/apex/file_contexts
index 27be16b..6d231f8 100644
--- a/sensors/aidl/default/apex/file_contexts
+++ b/sensors/aidl/default/apex/file_contexts
@@ -1,5 +1,3 @@
-(/.*)?							u:object_r:vendor_file:s0
-# Permission XMLs
-/etc/permissions(/.*)?					u:object_r:vendor_configs_file:s0
-# Service binary
-/bin/hw/android\.hardware\.sensors-service\.example	u:object_r:hal_sensors_default_exec:s0
\ No newline at end of file
+(/.*)?                                                u:object_r:vendor_file:s0
+/etc(/.*)?                                            u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.sensors-service\.example   u:object_r:hal_sensors_default_exec:s0
\ No newline at end of file
diff --git a/thermal/2.0/default/Android.bp b/thermal/2.0/default/Android.bp
index f743ade..83afa97 100644
--- a/thermal/2.0/default/Android.bp
+++ b/thermal/2.0/default/Android.bp
@@ -22,23 +22,13 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-filegroup {
-    name: "android.hardware.thermal@2.0-service.xml",
-    srcs: ["android.hardware.thermal@2.0-service.xml"],
-}
-
-filegroup {
-    name: "android.hardware.thermal@2.0-service.rc",
-    srcs: ["android.hardware.thermal@2.0-service.rc"],
-}
-
 cc_binary {
     name: "android.hardware.thermal@2.0-service.mock",
     defaults: ["hidl_defaults"],
     relative_install_path: "hw",
     vendor: true,
-    init_rc: [":android.hardware.thermal@2.0-service.rc"],
-    vintf_fragments: [":android.hardware.thermal@2.0-service.xml"],
+    init_rc: ["android.hardware.thermal@2.0-service.rc"],
+    vintf_fragments: ["android.hardware.thermal@2.0-service.xml"],
     srcs: [
         "Thermal.cpp",
         "service.cpp",
diff --git a/thermal/2.0/default/apex/Android.bp b/thermal/2.0/default/apex/Android.bp
deleted file mode 100644
index 914a3a8..0000000
--- a/thermal/2.0/default/apex/Android.bp
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2022 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
-    default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-apex_key {
-    name: "com.android.hardware.thermal.key",
-    public_key: "com.android.hardware.thermal.avbpubkey",
-    private_key: "com.android.hardware.thermal.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.thermal.certificate",
-    certificate: "com.android.hardware.thermal",
-}
-
-genrule {
-    name: "com.android.hardware.thermal.rc-gen",
-    srcs: [":android.hardware.thermal@2.0-service.rc"],
-    out: ["com.android.hardware.thermal.rc"],
-    cmd: "sed -E 's/\\/vendor/\\/apex\\/com.android.hardware.thermal.mock/' $(in) > $(out)",
-}
-
-prebuilt_etc {
-    name: "com.android.hardware.thermal.rc",
-    src: ":com.android.hardware.thermal.rc-gen",
-    installable: false,
-}
-
-apex {
-    name: "com.android.hardware.thermal.mock",
-    manifest: "manifest.json",
-    file_contexts: "file_contexts",
-    key: "com.android.hardware.thermal.key",
-    certificate: ":com.android.hardware.thermal.certificate",
-    use_vndk_as_stable: true,
-    updatable: false,
-    soc_specific: true,
-    binaries: ["android.hardware.thermal@2.0-service.mock"],
-    prebuilts: ["com.android.hardware.thermal.rc"],
-    vintf_fragments: [":android.hardware.thermal@2.0-service.xml"],
-}
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.avbpubkey b/thermal/2.0/default/apex/com.android.hardware.thermal.avbpubkey
deleted file mode 100644
index 8f7cf72..0000000
--- a/thermal/2.0/default/apex/com.android.hardware.thermal.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.pem b/thermal/2.0/default/apex/com.android.hardware.thermal.pem
deleted file mode 100644
index 4ea6e85..0000000
--- a/thermal/2.0/default/apex/com.android.hardware.thermal.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.pk8 b/thermal/2.0/default/apex/com.android.hardware.thermal.pk8
deleted file mode 100644
index 3e5bf69..0000000
--- a/thermal/2.0/default/apex/com.android.hardware.thermal.pk8
+++ /dev/null
Binary files differ
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.x509.pem b/thermal/2.0/default/apex/com.android.hardware.thermal.x509.pem
deleted file mode 100644
index 048e69a..0000000
--- a/thermal/2.0/default/apex/com.android.hardware.thermal.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF3TCCA8UCFFWeg2KJX/fyAqZPcKaFS61/a3GiMA0GCSqGSIb3DQEBCwUAMIGp
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTElMCMGA1UEAwwcY29t
-LmFuZHJvaWQuaGFyZHdhcmUudGhlcm1hbDAgFw0yMTExMTcxODE3MjRaGA80NzU5
-MTAxNDE4MTcyNFowgakxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
-MRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYD
-VQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
-MSUwIwYDVQQDDBxjb20uYW5kcm9pZC5oYXJkd2FyZS50aGVybWFsMIICIjANBgkq
-hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2W8QhCKX0WoS5jhIWbWBoKulD6XhKASA
-CL0oU6Uci0U6id2m++ou/T0aHSlliS9kT1NEABNwbLeTDa9h1qg1lbajRzXbvzEz
-EvZYT+dlgYFNZ9zaVCIlMapoiN+nrM/Rs24UBjJrZu1B39+IcE5ciQz69PgrLKWF
-vFEdYzxWI246azOVr3fvdelQg+CyPgiGObVAGOHhAidvsjg4FssKnADzn+JNlTt6
-b9P65xUQErut8hz9YdLtfZ096iwe8eEpsMOQwCNdKNXVCcNjQWkOwRaU+0awHoH1
-4mArvF7yyvJxqzkNaR03BPqXAHPIAPu6xdfA19+HVIiz6bLEZ1mfCM6edXByCWZu
-K8o54OZph71r15ncv4DVd+cnBjNvBvfdlJSeGjSreFkUo5NkfAwqdmLfZx6CedHI
-sLx7X8vPYolQnR4UEvaX6yeNN0gs8Dd6ePMqOEiwWFVASD+cbpcUrp09uzlDStGV
-1DPx/9J2kw8eXPMqOSGThkLWuUMUFojyh7bNlL16oYmEeZW6/OOXCOXzAQgJ7NIs
-DA1/H2w1HMHWgSfF4y+Es2CiqcgVFOIU/07b31Edw4v56pjx1CUpRpJZjDA1JJNo
-A4YCnpA6JWTxzUTmv21fEYyY+poA3CuzvCfZ80z9h/UFW98oM9GawGvK0i2pLudS
-RaZXWeil08cCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAj2gpn/IpAHQLDlI52WwL
-IDc5uzlf1BGseLZ8M8uuMiwvN00nOjunQQZEIbhH7+03GYyMzRhTTI3nWwmX4Fnq
-vC5sR68yNlu9gOAMXaAHo/Rw73ak7sv8xGbb2FeQsHaMKDQ2nqxP17SWdQ0xWa1u
-5qNurPOdAPOw77noZcT7yYX7lcrOKxPIekPJxyeOlp4bQSmabSRgYr70B7GybPlv
-K1gkgCBxl5RiVjVxLo+7ESHSAaGLy0S7F2v6PJ9oj15TovWQ0py2iBKZ6HReB7s/
-umnQqkwXDLudlNmoXIsgIYn8vKFTYpy1GSNJqhRSLfvLR6NtuU0iCTvg/X7oPmS1
-dWUdjVeO7ZVvIpO3gLLEe4maBEYF2sOlt3bRmzIHydORJtkfTt5tiZ4wR9RfJbkj
-iBiDbNiX010bZPTAXmgMbuJzQXZEXCBy0qKeS1cHwf9M8FDoiLajXepfZIp+6syt
-D4lZk4eAV141JL5PfABfdZWwT3cTgFIqCYpqrMQJIu+GHEjUwD2yNPi0I1/ydFCW
-CPDnzWjYCi6yVB8hss3ZFbvhfyJzdm3LivNVbLGK0+TG0EOAz6d2aQ0UjESgMD1A
-U8hLzQt7MiFSG0bt2cVx6SgCHeYUqMntbFELEAURWrhAfPLMJtAvFgKbEiZEAkkW
-pdDVh603aIp4LjVCfTYp/mQ=
------END CERTIFICATE-----
diff --git a/thermal/2.0/default/apex/file_contexts b/thermal/2.0/default/apex/file_contexts
deleted file mode 100644
index e0d87c7..0000000
--- a/thermal/2.0/default/apex/file_contexts
+++ /dev/null
@@ -1,5 +0,0 @@
-(/.*)?                                                    u:object_r:vendor_file:s0
-# Permission XMLs
-/etc/permissions(/.*)?                                    u:object_r:vendor_configs_file:s0
-# binary
-/bin/hw/android\.hardware\.thermal@2\.0-service\.mock     u:object_r:hal_thermal_default_exec:s0
diff --git a/thermal/2.0/default/apex/manifest.json b/thermal/2.0/default/apex/manifest.json
deleted file mode 100644
index ee44dc1..0000000
--- a/thermal/2.0/default/apex/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "com.android.hardware.thermal.mock",
-  "version": 1
-}
diff --git a/threadnetwork/aidl/default/thread_chip.cpp b/threadnetwork/aidl/default/thread_chip.cpp
index 9358eba..ed34e63 100644
--- a/threadnetwork/aidl/default/thread_chip.cpp
+++ b/threadnetwork/aidl/default/thread_chip.cpp
@@ -32,23 +32,19 @@
 namespace threadnetwork {
 
 ThreadChip::ThreadChip(char* url) : mUrl(), mRxFrameBuffer(), mCallback(nullptr) {
-    static const char kHdlcProtocol[] = "spinel+hdlc";
-    static const char kSpiProtocol[] = "spinel+spi";
-    const char* protocol;
+    const char* interfaceName;
 
     CHECK_EQ(mUrl.Init(url), 0);
 
-    protocol = mUrl.GetProtocol();
-    CHECK_NE(protocol, nullptr);
+    interfaceName = mUrl.GetProtocol();
+    CHECK_NE(interfaceName, nullptr);
 
-    if (memcmp(protocol, kSpiProtocol, strlen(kSpiProtocol)) == 0) {
-        mSpinelInterface = std::make_shared<ot::Posix::SpiInterface>(handleReceivedFrameJump, this,
-                                                                     mRxFrameBuffer);
-    } else if (memcmp(protocol, kHdlcProtocol, strlen(kHdlcProtocol)) == 0) {
-        mSpinelInterface = std::make_shared<ot::Posix::HdlcInterface>(handleReceivedFrameJump, this,
-                                                                      mRxFrameBuffer);
+    if (ot::Posix::SpiInterface::IsInterfaceNameMatch(interfaceName)) {
+        mSpinelInterface = std::make_shared<ot::Posix::SpiInterface>(mUrl);
+    } else if (ot::Posix::HdlcInterface::IsInterfaceNameMatch(interfaceName)) {
+        mSpinelInterface = std::make_shared<ot::Posix::HdlcInterface>(mUrl);
     } else {
-        ALOGE("The protocol \"%s\" is not supported", protocol);
+        ALOGE("The interface \"%s\" is not supported", interfaceName);
         exit(EXIT_FAILURE);
     }
 
@@ -106,7 +102,8 @@
     if (in_callback == nullptr) {
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     } else if (mCallback == nullptr) {
-        if (mSpinelInterface->Init(mUrl) != OT_ERROR_NONE) {
+        if (mSpinelInterface->Init(handleReceivedFrameJump, this, mRxFrameBuffer) !=
+            OT_ERROR_NONE) {
             return errorStatus(ERROR_FAILED, "Failed to initialize the interface");
         }
 
diff --git a/threadnetwork/aidl/default/thread_chip.hpp b/threadnetwork/aidl/default/thread_chip.hpp
index 680580a..30046ef 100644
--- a/threadnetwork/aidl/default/thread_chip.hpp
+++ b/threadnetwork/aidl/default/thread_chip.hpp
@@ -20,6 +20,7 @@
 #include <aidl/android/hardware/threadnetwork/IThreadChipCallback.h>
 
 #include "lib/spinel/spinel_interface.hpp"
+#include "lib/url/url.hpp"
 #include "mainloop.hpp"
 
 #include <android/binder_auto_utils.h>
diff --git a/tv/OWNERS b/tv/OWNERS
index ee7f272..e051b28 100644
--- a/tv/OWNERS
+++ b/tv/OWNERS
@@ -9,4 +9,5 @@
 quxiangfang@google.com
 shubang@google.com
 yixiaoluo@google.com
+qingxun@google.com
 
diff --git a/tv/input/OWNERS b/tv/input/OWNERS
index e69de29..1252e4e 100644
--- a/tv/input/OWNERS
+++ b/tv/input/OWNERS
@@ -0,0 +1 @@
+# Bug component: 826094
diff --git a/tv/tuner/aidl/vts/functional/FilterTests.cpp b/tv/tuner/aidl/vts/functional/FilterTests.cpp
index 53afef7..533d0e6 100644
--- a/tv/tuner/aidl/vts/functional/FilterTests.cpp
+++ b/tv/tuner/aidl/vts/functional/FilterTests.cpp
@@ -305,13 +305,18 @@
     ndk::ScopedAStatus status;
 
     status = mFilters[filterId]->configureMonitorEvent(monitorEventTypes);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult FilterTests::testMonitorEvent(uint64_t filterId, uint32_t monitorEventTypes) {
+    EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
     if (monitorEventTypes & static_cast<int32_t>(DemuxFilterMonitorEventType::SCRAMBLING_STATUS)) {
         mFilterCallbacks[filterId]->testFilterScramblingEvent();
     }
     if (monitorEventTypes & static_cast<int32_t>(DemuxFilterMonitorEventType::IP_CID_CHANGE)) {
         mFilterCallbacks[filterId]->testFilterIpCidEvent();
     }
-    return AssertionResult(status.isOk());
+    return AssertionResult(true);
 }
 
 AssertionResult FilterTests::startIdTest(int64_t filterId) {
diff --git a/tv/tuner/aidl/vts/functional/FilterTests.h b/tv/tuner/aidl/vts/functional/FilterTests.h
index f579441..f57093e 100644
--- a/tv/tuner/aidl/vts/functional/FilterTests.h
+++ b/tv/tuner/aidl/vts/functional/FilterTests.h
@@ -124,6 +124,7 @@
     AssertionResult configAvFilterStreamType(AvStreamType type, int64_t filterId);
     AssertionResult configIpFilterCid(int32_t ipCid, int64_t filterId);
     AssertionResult configureMonitorEvent(int64_t filterId, int32_t monitorEventTypes);
+    AssertionResult testMonitorEvent(uint64_t filterId, uint32_t monitorEventTypes);
     AssertionResult getFilterMQDescriptor(int64_t filterId, bool getMqDesc);
     AssertionResult startFilter(int64_t filterId);
     AssertionResult stopFilter(int64_t filterId);
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
index 9db82c8..3664b6c 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -60,6 +60,11 @@
     }
     ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
+    if (filterConf.monitorEventTypes > 0) {
+        ASSERT_TRUE(mFilterTests.testMonitorEvent(filterId, filterConf.monitorEventTypes));
+    }
+    ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
     ASSERT_TRUE(mFilterTests.stopFilter(filterId));
     ASSERT_TRUE(mFilterTests.closeFilter(filterId));
     ASSERT_TRUE(mDemuxTests.closeDemux());
diff --git a/usb/aidl/default/Android.bp b/usb/aidl/default/Android.bp
index 472e732..2c6ed07 100644
--- a/usb/aidl/default/Android.bp
+++ b/usb/aidl/default/Android.bp
@@ -43,9 +43,11 @@
     ],
 }
 
-filegroup {
+prebuilt_etc {
     name: "android.hardware.usb-service.example.xml",
-    srcs: ["android.hardware.usb-service.example.xml"],
+    src: "android.hardware.usb-service.example.xml",
+    sub_dir: "vintf",
+    installable: false,
 }
 
 filegroup {
diff --git a/usb/apex/Android.bp b/usb/aidl/default/apex/Android.bp
similarity index 70%
rename from usb/apex/Android.bp
rename to usb/aidl/default/apex/Android.bp
index 765aa21..29278dd 100644
--- a/usb/apex/Android.bp
+++ b/usb/aidl/default/apex/Android.bp
@@ -16,33 +16,22 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-apex_key {
-    name: "com.android.hardware.usb.key",
-    public_key: "com.android.hardware.usb.avbpubkey",
-    private_key: "com.android.hardware.usb.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.usb.certificate",
-    certificate: "com.android.hardware.usb",
-}
-
 apex {
     name: "com.android.hardware.usb",
     manifest: "manifest.json",
     file_contexts: "file_contexts",
-    key: "com.android.hardware.usb.key",
-    certificate: ":com.android.hardware.usb.certificate",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
     updatable: false,
-    soc_specific: true,
-    use_vndk_as_stable: true,
+    vendor: true,
+
     binaries: ["android.hardware.usb-service.example"],
     prebuilts: [
         "com.android.hardware.usb.rc", // init .rc
         "android.hardware.usb.accessory.prebuilt.xml",
         "android.hardware.usb.host.prebuilt.xml",
+        "android.hardware.usb-service.example.xml",
     ],
-    vintf_fragments: [":android.hardware.usb-service.example.xml"],
 }
 
 // Replace the binary path from /vendor/bin to /apex/{name}/bin in the init .rc file
@@ -50,7 +39,7 @@
     name: "com.android.hardware.usb.rc-gen",
     srcs: [":android.hardware.usb-service.example.rc"],
     out: ["com.android.hardware.usb.rc"],
-    cmd: "sed -E 's/\\/vendor/\\/apex\\/com.android.hardware.usb/' $(in) > $(out)",
+    cmd: "sed -E 's@/vendor/bin@/apex/com.android.hardware.usb/bin@' $(in) > $(out)",
 }
 
 prebuilt_etc {
diff --git a/usb/aidl/default/apex/file_contexts b/usb/aidl/default/apex/file_contexts
new file mode 100644
index 0000000..53404f7
--- /dev/null
+++ b/usb/aidl/default/apex/file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                                 u:object_r:vendor_file:s0
+/etc(/.*)?                                             u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.usb-service\.example        u:object_r:hal_usb_default_exec:s0
\ No newline at end of file
diff --git a/usb/apex/manifest.json b/usb/aidl/default/apex/manifest.json
similarity index 100%
rename from usb/apex/manifest.json
rename to usb/aidl/default/apex/manifest.json
diff --git a/usb/apex/com.android.hardware.usb.avbpubkey b/usb/apex/com.android.hardware.usb.avbpubkey
deleted file mode 100644
index 0302d63..0000000
--- a/usb/apex/com.android.hardware.usb.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/usb/apex/com.android.hardware.usb.pem b/usb/apex/com.android.hardware.usb.pem
deleted file mode 100644
index e1e57da..0000000
--- a/usb/apex/com.android.hardware.usb.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEAwdimmHgIZHrep3H3YfVaNYEAGg45LUEPIiwHV6aIC9V7zjBS
-SftD30Z21jGyk7hmtas6WMI2vRBDNGrZWDgPeiEQoxXQinuU4Ug5S5X2F8LpWs0y
-ZeNFwQkqZwqGdQlkmy8upfb6T7rDxqRv+C0AtGP1r4r36+Xh5ld5stVaMK0UNhZt
-VW0nQAxyeJL3tm0zfiEA9Zu7FF2IyHm+bo9+eJ7WXfjiJfkclLgqlX3ec2cvVqAf
-NHisj18PEd/qtC64b+FnkgbsdHzWbo8HW5x4STkGXNnH+O3dvkWBX60MOfywfZFw
-+yaz5mt7K+ft/V4UA7zKiAEFM+J1lND9/UMJnd0XMYYtcRQF8lmu4dlcjfbbAm0k
-VgoUEsizIeMPLrMj837uVloKKzIXmPsVsfMarP/MrX6TJfzdUhdm01pVO1g0wtHJ
-J3eYQsEnOI7RjL+uZDQvPWAnr71pvacn66PAJC1UPulEEla5lhd30RDItbJkngXp
-3UggW32ZOQt3Oc8P0eo9SCnBlHtCVr8wfxAbxCoPR9qIdX3azkQRqcKqGbBbPnkc
-hSCzeIofUkYGibfbZg4k1yY82xEqZuN7J1zycoGP4wyhXeRLTRWxfPR5dxxmQZaS
-67A1LWrYvAzF8Rd44VMRlI/Qk6zuBsL01j2dfBqit+le+viQmTYb3BpV+1kCAwEA
-AQKCAgAmSfX2LddyiXaLWo6DsePkp5tuihqvHqevl0TIAmPi+oMe4hqO9GueoZt9
-iYl9djILdkvrFkmbpKexpd1SeJhOBlPz8q4jfG+W5B41GOToIp7XSarHx1GS5I2U
-ltaiLX3KzVIIhDVDJF/hT7+yJKl7+DaiOu/nj5vEVMj8EvpinP1eBaYI9quHEi5W
-NKlrRjyikEBRQzZ7ulH3T1zXF87iYnVzUGLTH1aO5aW7q4YSA3KtSKmBQsjK9PrU
-DAefGY9iwgIkLOvtwm7UnbnVVZ3I0NO56WZ/e/SNzcrVLCg7F/eAhgbsBOQKAnbs
-4D35CuknJ9ZVcOYnLncNMw7IRMKULKYLAuLLN1X33y22qaVxYA42rq13mZrijlua
-CMQ2Ur+GNcq8OI3mRDO38yKeJ5b4885LQdlrXXyoGnSjlkU5n8U9Jw6q2rZGiWlk
-4Q71g+KUl0rtXSnFSIJLNTK6Cd3ETStxswLvvCvfLTrRQcO8f2SdVxblmsc9eCDs
-JUxz6Sahkpb9hsY8fozu6laXC/5Ezy0TinRgGjQM/DQqbXtFXgse56mDxzSho5oh
-Spy3X7Q/v4VUtrSKsEZEIEVWCpplzVULpHenCDbU58rHyEcS7ew+kwlfHC73iEhX
-HPujSIKvStO7yCEeY6IdhON8iVX34uvQeAgEe4+rehQHLZUg0QKCAQEA9AS3imKF
-yEt0yNRLcdXSqYkak+OM2kfhBBcLndCT7Terr6yluv/SkPGYjUbmr2XiygMv8IwO
-8f+KbWsNwYCaB22HVYVGL0oUYAlCvWhnia3Iwn6ZZuXuJv5mmfqt/GMlaIfohNLy
-zI2OlcpcAuRfNlenjNyd+inxwdXL28Z86kbabnUlijgqpu4KFOYOlxbTRv93IlfM
-Ico1pZkLS1glDMFLetF+IWq4zqpXrdgNUk1KX3sofOCfZQnlWFrrHbXJPCgPAtlv
-xP4dmJQgtWkWwxUlelfz34LcCUVX2aTlgKjuvgvyCt2ZPWixXbDtjsCBTn3xBhoY
-kDp2OyMC+d543QKCAQEAy11GpYOQvTMKbV07EmN9jTRYg7gRrxsT3Kd4Xy+NpIY8
-v6J5Keeppk9t6WBrJi2cQU/EoHcd3fRkWMnWMNorZDiCu34VG5bfa4pTqnSLdLC4
-/e5UHdHqCy9deAwhlHYWbAx0KnxXWGxkq05dXvQsVuOtAs528NcujnLpwDONQt5P
-e3RIZmOOjr+7rqGp3vA9SuNOINOQpeKxQT6GRGw4mlYofdwOPaE1wCsO8vQCNmCJ
-DEfdm+hWjTLAV2IBCfi5BKRsIAXrABPzkzDeLGDmaQkJTDpK8UQcrFnqItGeo+yl
-fDjxA0zAPWYGcyXcXbtvayX+zCk/SKwQABqUtaumrQKCAQEA0mdizwsGqd8OMsCC
-0QP64j4a0Zvqbqh9yCYK2Sfo9SkEe7SVLnm5WUtIK8EP1fs3ItK+ul454MZj2Nbv
-BINbzL3PbJk/HDV2/hveFS154UgcjD/XC9eEktDXLTvuW2ot7kUJ48V0n5YLdPMI
-hWHfCx9nlFkCSptyHp23aqhqOyOe4pFWLikh9c/Yl46K1BJVWKmcUtt7Y0NVIJWn
-HG9Dew0MhTkv1aaM9X4Bnh9l1SpZz5yFG7AfIGL5A0dZ5cNCYgF0eBN+gVBPuqk2
-ztVvUATizOwblwThr4jAKCU70sVXHj10lZPftwiXrt6I54brt/92HLnRpkMSgQk+
-Xq9KbQKCAQAXxPM47UPBmXGijr8UyyQlmPSvkJggi12q8LgVCA3aKQZ4r5jR2Q3v
-LmF+YZKkh7g3ugcValbHVoVUC2NJmnZv5FsDZx04eE3s1+Inji+ul+lHZM/YHGzq
-mcKnAWP7YkIEpv/850OeRi0OCL7JFmkITtwt88vbIouCgtPnbx8XrbxEhbbgoMpM
-zQQ2yRZ9xD6lviOnmpLRkMl/ArvWy39iKqfY7huMAIezylSY+QQ5LtdV5CB21JUp
-M8FfdUkBzVxyunUY2Rg6jhpuHcwaC8lihXfcvQN9Z6SiUHAZWb7dEg/VkSI6bIIb
-qw0d8FLtcbb4IxzA6CFJcTL9kB3JjiKRAoIBAQC15t3mQHb9iCM4P4U9fpR4syvN
-46vDMhtj3vejerzOro2R7UUCJDvT59DrCQvtKO/ZCyhdTyuyResu6r1vbwq3KWiB
-i0RIeW87cKgJRr6w+KivB+a805WfI9zNRz778b7ajEpBkOs4vRPWu6S1306tdvgM
-Dhj7GT9UFh/k7pNuoSbiuaPUqgZRP55nzgj/FoIN985wnxo/ugckSqZ1bFGFXhYt
-zfIdFvPkf1BlLCnLTE8yESsJ3P37Gfj2XRv9h2I2/8qAGZniKtbVWHlu+5LDJf6V
-x9VpDAH2ZQAqRC3za3gfTjMsglYi7mUDeMYlB4osURNt7jDtElEmsto7AAkI
------END RSA PRIVATE KEY-----
diff --git a/usb/apex/com.android.hardware.usb.pk8 b/usb/apex/com.android.hardware.usb.pk8
deleted file mode 100644
index 9f3f39b..0000000
--- a/usb/apex/com.android.hardware.usb.pk8
+++ /dev/null
Binary files differ
diff --git a/usb/apex/com.android.hardware.usb.x509.pem b/usb/apex/com.android.hardware.usb.x509.pem
deleted file mode 100644
index 210c30d..0000000
--- a/usb/apex/com.android.hardware.usb.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF1TCCA70CFFEdsyLGoTRk+VIzqb6aDl1tXeuZMA0GCSqGSIb3DQEBCwUAMIGl
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEhMB8GA1UEAwwYY29t
-LmFuZHJvaWQuaGFyZHdhcmUudXNiMCAXDTIxMTExNzIyMzAwM1oYDzQ3NTkxMDE0
-MjIzMDAzWjCBpTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAU
-BgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNVBAsM
-B0FuZHJvaWQxIjAgBgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5kcm9pZC5jb20xITAf
-BgNVBAMMGGNvbS5hbmRyb2lkLmhhcmR3YXJlLnVzYjCCAiIwDQYJKoZIhvcNAQEB
-BQADggIPADCCAgoCggIBAM2E0E9ubNU/or7r9UIcFrC4l7CeM0HwtwSjTUKV1Z9K
-7rPFoUPE3cQ+cResnWQay8IGnomLYptAIMe8sLCC83LwU1ucTihxX87qq2W3V14w
-U4AkqDzNvYqKiD3yz9WofKxcu7ut8+1O4Pvp11X8UXuy5kNzf8WGpGB04k6U6KtA
-q8+U8+4h9h1Uvhaa0AeG9Yp22LzRLTb3J+eCoGHJnjoXYsd9T/gvedyXKkuf0lWB
-b3Aor3/CQrpdCW2/iJbuASdBdfilpQShaagxy2wmQsYxnT8ZWf+tIDYjg3xqqVPl
-GChFwCQBdaTuLI/k9gbaXkSxuzRkp5wc/ELhYbkhIS25yefAF2C6num++AHQBh1+
-qO0fHztsK80c5cVoDPWu17/nP7y3QloRyLFUrL3hVW1RQaFwE2Hmv4H0UwVAsleU
-ZIsz2ifTjiSl/tnkFTx0I6BVk7T87QhO3WXN4v6VDYZKeD4gQYS0NfwplahejrFw
-s3EcwKgt6f0KlIpzoEQBmNQBXxsRgL31GWCwCszb7+VrTMzgUpO41R3PyewbeaZk
-S/SHyEOwyf0WIvnZhZ/5CNd9qirClu6jS8kdLvwC2qA25VqSPw126EX1e2xUqm02
-C/6c7JDVocuQhvsJOnnpZt68Iwgw9g/xLCLA9RszH9ccRctZqRnzHB1AjTrBOq0P
-AgMBAAEwDQYJKoZIhvcNAQELBQADggIBAELbSot2Io/JZIYLTxgeReI4lk1KUzf8
-fGlDNlRm+goxOHXWQgvXgiftwM9IOB+H+EtNHAA9Q6ojAmfRe6rZC4p0ZxWOamtR
-V+pQj0c6Zvx8HJPMQdyoHx538iNXM093s2wnf+QuACb3BnvkK7uuLGAlIzWdImtL
-DKKFN05nppViY04tGP5HgT57b7YGwdkEp6euCJcyWIKjlyEH/bwTWM8ws/Px6uhw
-+5W2K7KrBsdRKPBF7qwXoS8Ak8pS5de9Xd7mbGBLaUtjsZ0pJbq0aFpuT0GbLWUm
-wiD5Ljq3ea/2GZxbHGiXQ2yNjFSd/jpuxDnnm99t7+HGw1v5Jld+hUVqXXfVNhWe
-hUKIv5TOk1nttNdsaLyDtxyt22JX7NnoPM0MqrkYwA8Xqrbv0VC8D/CVjiBC9Tce
-crhpCISNfQSkdEn/c+q/naFUvQy8oYqXkg1TjeGlcxwJOpGliYbbYT6VAwuI/ssI
-yX3Fkr8f5KhfN2aFnOpidknmLp9EyL2j5bxAtSD9xAHtczMn10uCUdLELjRB1L4f
-1qY+EjpIgK0NIFuEt9K5uZXirXq3K3eixKeJFNji3x/X8NgDALSdnT8JIlSg4DMg
-iWupLrQ9CSHMlgh5P43ALamiRIHQNqEwgj8OIGzsvQTSLbRjbPWYcDZa+Q1hosiA
-Fv7vjDI6oySM
------END CERTIFICATE-----
diff --git a/usb/apex/file_contexts b/usb/apex/file_contexts
deleted file mode 100644
index f223a56..0000000
--- a/usb/apex/file_contexts
+++ /dev/null
@@ -1,5 +0,0 @@
-(/.*)?                                         u:object_r:vendor_file:s0
-# Permission XMLs
-/etc/permissions(/.*)?                         u:object_r:vendor_configs_file:s0
-# binary
-/bin/hw/android\.hardware\.usb-service\.example        u:object_r:hal_usb_default_exec:s0
\ No newline at end of file
diff --git a/uwb/aidl/default/Android.bp b/uwb/aidl/default/Android.bp
index 916646c..f9b79de 100644
--- a/uwb/aidl/default/Android.bp
+++ b/uwb/aidl/default/Android.bp
@@ -48,23 +48,12 @@
     installable: false,
 }
 
-apex_key {
-    name: "com.android.hardware.uwb.key",
-    public_key: "com.android.hardware.uwb.avbpubkey",
-    private_key: "com.android.hardware.uwb.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.uwb.certificate",
-    certificate: "com.android.hardware.uwb",
-}
-
 apex {
     name: "com.android.hardware.uwb",
     manifest: "manifest.json",
     file_contexts: "file_contexts",
-    key: "com.android.hardware.uwb.key",
-    certificate: ":com.android.hardware.uwb.certificate",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
     updatable: false,
     vendor: true,
 
diff --git a/uwb/aidl/default/com.android.hardware.uwb.avbpubkey b/uwb/aidl/default/com.android.hardware.uwb.avbpubkey
deleted file mode 100644
index 7a7fce8..0000000
--- a/uwb/aidl/default/com.android.hardware.uwb.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/uwb/aidl/default/com.android.hardware.uwb.pem b/uwb/aidl/default/com.android.hardware.uwb.pem
deleted file mode 100644
index cd38ef8..0000000
--- a/uwb/aidl/default/com.android.hardware.uwb.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-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
-vApJsLERxjCi0eqDwVx/e6xbeOVUZc/m
------END PRIVATE KEY-----
diff --git a/uwb/aidl/default/com.android.hardware.uwb.pk8 b/uwb/aidl/default/com.android.hardware.uwb.pk8
deleted file mode 100644
index 8855197..0000000
--- a/uwb/aidl/default/com.android.hardware.uwb.pk8
+++ /dev/null
Binary files differ
diff --git a/uwb/aidl/default/com.android.hardware.uwb.x509.pem b/uwb/aidl/default/com.android.hardware.uwb.x509.pem
deleted file mode 100644
index 762ad88..0000000
--- a/uwb/aidl/default/com.android.hardware.uwb.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF1TCCA70CFEagTJLwbnblSQu8MjFHXcEDFQ1MMA0GCSqGSIb3DQEBCwUAMIGl
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEhMB8GA1UEAwwYY29t
-LmFuZHJvaWQuaGFyZHdhcmUudXdiMCAXDTIzMDgyMTA0MTE0M1oYDzQ3NjEwNzE3
-MDQxMTQzWjCBpTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAU
-BgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNVBAsM
-B0FuZHJvaWQxIjAgBgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5kcm9pZC5jb20xITAf
-BgNVBAMMGGNvbS5hbmRyb2lkLmhhcmR3YXJlLnV3YjCCAiIwDQYJKoZIhvcNAQEB
-BQADggIPADCCAgoCggIBAJpvvE7i50v4hE5VmlFTiOsQ+zOYWF+MjzEMXcqLQDzs
-26XBYJV7O3TwgrQNp1XV8KCPTAF8APEyGb237rlZO/3KvS9zYa3zFfEMPg5pnFmR
-QLWSfqrXm7ttKIQHNVAjqrLnlt8pjvKS/t/UXLAWgHiXnd2ZX62tQjyDouszLEwP
-59zJbkgX9o6fwEssdRTpuyoRoyPylfK3Thk22RBSTt+pS6pwqeUj4vttrPr7k7YU
-S5CeB7XVBRPRzXFrpasgzQqp2deOpqxC44H90+pl7QmBHFrnGk+90lcOPYgqF2Ah
-DfCBxAHzn8ioSsAJ0U34yqoNbWIUX3ZHgq1ru1uctdLwGMrKmqsw4uvfXLV+sjoi
-qUFW+9uEOHAVnmZEO2T7LAlUIoAGgdd58EJ+hdXP2yvNpGVPestrwWttAaMJoEJN
-qEWt67+iEjdEpVn0lUFo+up42mYEXGUAOpoc6t5WJinrQTY4JK/OIGJPUiOjbUTI
-T/hQTddr0HNGsKP2zRv0d49VtVht6wR0HlO1srCFZAGxRIdBtjjenu1l7ALMWlHw
-4YXLSpQoeYfavV8C3j5bzz6KaDj6HcKvRbyHRX8+JL9kFDgpOD1yI/jaaPepRAe6
-qek5jEJMEFj0tFifB8e0CZbURreXa1tErWybfuDkaNBDtAHL333/IQGI0vV7zr0x
-AgMBAAEwDQYJKoZIhvcNAQELBQADggIBAFqnBngYd7rXHwIXHYKZuRMf+NLQxNFN
-f0m6ioFYgNnMwoMQidBHdRsJ2qTb9zfyt5O1/5Wel8Ix9aUCRbJejyX2lYXNIJNC
-ykahkoP+3CEA8QtPkmtWzNraDJRh2eYn6V5DJOWyvkz02DsHA4mxatYkF7dUfqLx
-f/y1y3cbnTyAraotTRb3W/F/zEYbcCzwlFZDT/IASVM89WRDE76+rp7/wDNJ0aEJ
-l6cQaUWDPbrvDWZaptRWfnebPtg81v03qKauwrBADddxu+/Nqs0iczBdsP1tdXr/
-Hxs47D7+fZnytVQglldBG4yky9YceL22yft/bCNDe5d7nF1/iUpJNbRIcrZxD86Z
-wwPpo0VMJ+r6VuD6UGQTS6Zyi94QD3GYYkGrPPwyrLKpp1EU6dV32bWCNp5eQojY
-FyTse/lfAJ9/Xu3klHYuR9xOaJiH+2MmtJTwKdjvK5h+EIiVbyrDJJHBd9sWav3a
-Emo+wKaIxQzXEUjWxUwy7eAAwq5WzawLMMQ97P0zIgasNIlUHW2cvBzVsQlM1tN7
-2t+7UPs5RifK5hadK6Ge1oqkG0xC1t65E7yGwrPMzKuz9aPgg7j1YAaETcKuFOHG
-rZr/0kALZc6VKNSZ8eM2P5ObrelLOe4ED9Ha1ZhmnCDXN9BP2gwqmCekwfNJ3cPA
-GObJiF81f9ZM
------END CERTIFICATE-----
diff --git a/vibrator/OWNERS b/vibrator/OWNERS
index 62a567e..c4de58a 100644
--- a/vibrator/OWNERS
+++ b/vibrator/OWNERS
@@ -1,8 +1,2 @@
 # Bug component: 345036
-
 include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
-
-chrispaulo@google.com
-michaelwr@google.com
-nathankulczak@google.com
-taikuo@google.com
diff --git a/vibrator/aidl/default/Android.bp b/vibrator/aidl/default/Android.bp
index 78bb4ed..fb71a82 100644
--- a/vibrator/aidl/default/Android.bp
+++ b/vibrator/aidl/default/Android.bp
@@ -32,9 +32,11 @@
     },
 }
 
-filegroup {
+prebuilt_etc {
     name: "android.hardware.vibrator.xml",
-    srcs: ["android.hardware.vibrator.xml"],
+    src: "android.hardware.vibrator.xml",
+    sub_dir: "vintf",
+    installable: false,
 }
 
 cc_binary {
diff --git a/vibrator/aidl/default/apex/Android.bp b/vibrator/aidl/default/apex/Android.bp
index 7949057..39626bf 100644
--- a/vibrator/aidl/default/apex/Android.bp
+++ b/vibrator/aidl/default/apex/Android.bp
@@ -2,17 +2,6 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-apex_key {
-    name: "com.android.hardware.vibrator.key",
-    public_key: "com.android.hardware.vibrator.avbpubkey",
-    private_key: "com.android.hardware.vibrator.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.vibrator.certificate",
-    certificate: "com.android.hardware.vibrator",
-}
-
 prebuilt_etc {
     name: "com.android.hardware.vibrator.rc",
     src: "com.android.hardware.vibrator.rc",
@@ -22,20 +11,19 @@
 apex {
     name: "com.android.hardware.vibrator",
     manifest: "apex_manifest.json",
-    key: "com.android.hardware.vibrator.key",
-    certificate: ":com.android.hardware.vibrator.certificate",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
     file_contexts: "file_contexts",
-    use_vndk_as_stable: true,
     updatable: false,
-    // Install the apex in /vendor/apex
-    soc_specific: true,
+    vendor: true,
+
     binaries: [
         "android.hardware.vibrator-service.example",
     ],
     prebuilts: [
         "com.android.hardware.vibrator.rc",
+        "android.hardware.vibrator.xml",
     ],
-    vintf_fragments: [":android.hardware.vibrator.xml"],
     // vibrator.default.so is not needed by the AIDL service binary.
     overrides: ["vibrator.default"],
 }
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.avbpubkey b/vibrator/aidl/default/apex/com.android.hardware.vibrator.avbpubkey
deleted file mode 100644
index a6ca630..0000000
--- a/vibrator/aidl/default/apex/com.android.hardware.vibrator.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.pem b/vibrator/aidl/default/apex/com.android.hardware.vibrator.pem
deleted file mode 100644
index c0f5c50..0000000
--- a/vibrator/aidl/default/apex/com.android.hardware.vibrator.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.pk8 b/vibrator/aidl/default/apex/com.android.hardware.vibrator.pk8
deleted file mode 100644
index d20cc33..0000000
--- a/vibrator/aidl/default/apex/com.android.hardware.vibrator.pk8
+++ /dev/null
Binary files differ
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.x509.pem b/vibrator/aidl/default/apex/com.android.hardware.vibrator.x509.pem
deleted file mode 100644
index 993245b..0000000
--- a/vibrator/aidl/default/apex/com.android.hardware.vibrator.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF3zCCA8cCFBJmLB9vGtl8nENMVa8g51Y2vRhPMA0GCSqGSIb3DQEBCwUAMIGq
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEmMCQGA1UEAwwdY29t
-LmFuZHJvaWQuaGFyZHdhcmUudmlicmF0b3IwIBcNMjEwOTE2MTcyOTA5WhgPNDc1
-OTA4MTMxNzI5MDlaMIGqMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5p
-YTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4G
-A1UECwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNv
-bTEmMCQGA1UEAwwdY29tLmFuZHJvaWQuaGFyZHdhcmUudmlicmF0b3IwggIiMA0G
-CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDV857uzUSXWQNWIuiNRwt1zd/eSB8P
-iVNq0qTexlZvamXr6h5VwX45iJeDVCxlx3uktXXP2NH7U01A5gl8Hix6iodNe3sJ
-fFIhzUiqdMfAn+6RWcJcb3v6J58D6R+htgtaSgv8WOLkIZyhbmU3NToc7dNe2j0U
-wh6xfYhpj/s0RManSTZW19C2H8g5eNfhEZgDT+KOUIgepv/x6Y5IR147JPh8Ha7g
-vxM87ceErSvr3e8uXDWUZtQ6IDfF2NkxJJGJos4IAteXbkG60q76V8pmWLCqIsMM
-tRcIpTEJUIbnbxAqSu+crZqQowu9HrJMYnqunlmXASeluxXdl8VKOVNMZHy3ipj7
-HjoTUJoiEVDLYeT7db76k2lDFH/JRtnoe3BBinUEKvGT3rOjy55C4E2DSMSM1Laz
-zkRcJ4hlzFQLXD5/iwWgW6me1lmnOEqFJZolc1fEc+VfEdZdwJmZF6Clm5av2hDm
-Oq09qL02nXy0OyAoCI6IcrrAlFFolgel32nWp1R7c+N2+6vLMP3KR50TgSiwHNNQ
-weZhpP1GrXDyVj+ilL5T/2ionvjIvDBgOi8B0IwiqeHY7lqsSyMOuKTi5WPrJ86E
-GNJ+PlivA/P9MAatem4kzCT2t3DbVC+dtybiUAmVFb2Ls+dVK4nHcbGTW9AuBijD
-COEHQgi4Xs6lnwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQDGvq99QUxMh+DaI2Pd
-s4fQ9MmYxGDxULhjqgGAjDbL3jQMG2FxPTu1Z2VJgg4n+PTNsgsqgn1JgQM3gvFp
-8FKhoxtzM5V8pPxphCG7U/f3ZsmXdLl69sbVkMRhorhQ8H54q0O/T3Ig/ULZgblE
-xCRT1REB693tUQOCYgWgnsOpvySfujYhNBirl48Hw9zrRmQNTsO20dKwkZUvkVow
-/pawucYrHibgwgKWz8kB3Dl4DODiLybek0hGzr59Joul9eMsxTuQsHAIUv0KO2Ny
-5WT7GIX6qYc+VrnXsO+PHtx5GTUjrJiue3aggoW6X7gu3Z6KuIOiVTVLVp6wSJtt
-VHv90HTu2lYxtPyPSOpFfwFOTicN+5VmLTQwPvPRqsnCaYc+K2iWyEhN/PnSfFNc
-t/TX9HT3ljXq9yfshQmQJ27pdUiYs9Avt7fEXpJjQ0Tn9w8jRS5gsrnTUXTG6HXf
-I4lsMSAApFZa112PwU7xAIIaipBauuMjQCabD/thBzB6d29Rlbz3cjBzoky9h2vb
-XNIVo5O2Jiz7OJQ/7mubvJqIBngiaDK78n2hSdYglI1hgcf0KaQIJUridzmjt0kp
-xXcwIz7nJxhNpbsYnDnqwqz9en8a4N+KeoQleYROo2kEtE434AJkzdABV4IKRafj
-cbPWuY6F2faWAjkSOEhBfGOKOw==
------END CERTIFICATE-----
diff --git a/vibrator/aidl/default/apex/file_contexts b/vibrator/aidl/default/apex/file_contexts
index f811656..f061caa 100644
--- a/vibrator/aidl/default/apex/file_contexts
+++ b/vibrator/aidl/default/apex/file_contexts
@@ -1,3 +1,4 @@
-(/.*)? 							u:object_r:vendor_file:s0
-/bin/hw/android\.hardware\.vibrator-service\.example	u:object_r:hal_vibrator_default_exec:s0
+(/.*)?                                                  u:object_r:vendor_file:s0
+/etc(/.*)?                                              u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.vibrator-service\.example    u:object_r:hal_vibrator_default_exec:s0
 
diff --git a/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp
index bebad7c..738e72c 100644
--- a/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp
@@ -76,18 +76,10 @@
 
     void TearDown() override { stopWifiService(getInstanceName()); }
 
-    // Used as a mechanism to inform the test about data/event callbacks.
-    inline void notify() {
-        std::unique_lock<std::mutex> lock(mtx_);
-        count_++;
-        cv_.notify_one();
-    }
-
     enum CallbackType {
-        INVALID = -2,
-        ANY_CALLBACK = -1,
+        INVALID = 0,
 
-        NOTIFY_CAPABILITIES_RESPONSE = 0,
+        NOTIFY_CAPABILITIES_RESPONSE = 1,
         NOTIFY_ENABLE_RESPONSE,
         NOTIFY_CONFIG_RESPONSE,
         NOTIFY_DISABLE_RESPONSE,
@@ -128,310 +120,278 @@
         EVENT_SUSPENSION_MODE_CHANGE,
     };
 
+    // Used as a mechanism to inform the test about data/event callbacks.
+    inline void notify(CallbackType callbackType) {
+        std::unique_lock<std::mutex> lock(mtx_);
+        callback_event_bitmap_ |= (UINT64_C(0x1) << callbackType);
+        cv_.notify_one();
+    }
+
     // Test code calls this function to wait for data/event callback.
-    // Must set callbackType = INVALID before calling this function.
+    // Must set callback_event_bitmap_ to 0 before calling this function.
     inline std::cv_status wait(CallbackType waitForCallbackType) {
         std::unique_lock<std::mutex> lock(mtx_);
         EXPECT_NE(INVALID, waitForCallbackType);
 
         std::cv_status status = std::cv_status::no_timeout;
         auto now = std::chrono::system_clock::now();
-        while (count_ == 0) {
+        while (!(receivedCallback(waitForCallbackType))) {
             status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
             if (status == std::cv_status::timeout) return status;
-            if (waitForCallbackType != ANY_CALLBACK && callback_type_ != INVALID &&
-                callback_type_ != waitForCallbackType) {
-                count_--;
-            }
         }
-        count_--;
         return status;
     }
 
+    inline bool receivedCallback(CallbackType waitForCallbackType) {
+        return callback_event_bitmap_ & (UINT64_C(0x1) << waitForCallbackType);
+    }
+
     class WifiNanIfaceEventCallback : public BnWifiNanIfaceEventCallback {
       public:
         WifiNanIfaceEventCallback(WifiNanIfaceAidlTest& parent) : parent_(parent){};
 
         ::ndk::ScopedAStatus eventClusterEvent(const NanClusterEventInd& event) override {
-            parent_.callback_type_ = EVENT_CLUSTER_EVENT;
             parent_.nan_cluster_event_ind_ = event;
-            parent_.notify();
+            parent_.notify(EVENT_CLUSTER_EVENT);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventDataPathConfirm(const NanDataPathConfirmInd& event) override {
-            parent_.callback_type_ = EVENT_DATA_PATH_CONFIRM;
             parent_.nan_data_path_confirm_ind_ = event;
-            parent_.notify();
+            parent_.notify(EVENT_DATA_PATH_CONFIRM);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventDataPathRequest(const NanDataPathRequestInd& event) override {
-            parent_.callback_type_ = EVENT_DATA_PATH_REQUEST;
             parent_.nan_data_path_request_ind_ = event;
-            parent_.notify();
+            parent_.notify(EVENT_DATA_PATH_REQUEST);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventDataPathScheduleUpdate(
                 const NanDataPathScheduleUpdateInd& event) override {
-            parent_.callback_type_ = EVENT_DATA_PATH_SCHEDULE_UPDATE;
             parent_.nan_data_path_schedule_update_ind_ = event;
-            parent_.notify();
+            parent_.notify(EVENT_DATA_PATH_SCHEDULE_UPDATE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventDataPathTerminated(int32_t ndpInstanceId) override {
-            parent_.callback_type_ = EVENT_DATA_PATH_TERMINATED;
             parent_.ndp_instance_id_ = ndpInstanceId;
-            parent_.notify();
+            parent_.notify(EVENT_DATA_PATH_TERMINATED);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventDisabled(const NanStatus& status) override {
-            parent_.callback_type_ = EVENT_DISABLED;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(EVENT_DISABLED);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventFollowupReceived(const NanFollowupReceivedInd& event) override {
-            parent_.callback_type_ = EVENT_FOLLOWUP_RECEIVED;
             parent_.nan_followup_received_ind_ = event;
-            parent_.notify();
+            parent_.notify(EVENT_FOLLOWUP_RECEIVED);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventMatch(const NanMatchInd& event) override {
-            parent_.callback_type_ = EVENT_MATCH;
             parent_.nan_match_ind_ = event;
-            parent_.notify();
+            parent_.notify(EVENT_MATCH);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventMatchExpired(int8_t discoverySessionId, int32_t peerId) override {
-            parent_.callback_type_ = EVENT_MATCH_EXPIRED;
             parent_.session_id_ = discoverySessionId;
             parent_.peer_id_ = peerId;
-            parent_.notify();
+            parent_.notify(EVENT_MATCH_EXPIRED);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventPublishTerminated(int8_t sessionId,
                                                     const NanStatus& status) override {
-            parent_.callback_type_ = EVENT_PUBLISH_TERMINATED;
             parent_.session_id_ = sessionId;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(EVENT_PUBLISH_TERMINATED);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventSubscribeTerminated(int8_t sessionId,
                                                       const NanStatus& status) override {
-            parent_.callback_type_ = EVENT_SUBSCRIBE_TERMINATED;
             parent_.session_id_ = sessionId;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(EVENT_SUBSCRIBE_TERMINATED);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventTransmitFollowup(char16_t id, const NanStatus& status) override {
-            parent_.callback_type_ = EVENT_TRANSMIT_FOLLOWUP;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(EVENT_TRANSMIT_FOLLOWUP);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventPairingConfirm(const NanPairingConfirmInd& event) override {
-            parent_.callback_type_ = EVENT_PAIRING_CONFIRM;
             parent_.nan_pairing_confirm_ind_ = event;
-            parent_.notify();
+            parent_.notify(EVENT_PAIRING_CONFIRM);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventPairingRequest(const NanPairingRequestInd& event) override {
-            parent_.callback_type_ = EVENT_PAIRING_REQUEST;
             parent_.nan_pairing_request_ind_ = event;
-            parent_.notify();
+            parent_.notify(EVENT_PAIRING_REQUEST);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventBootstrappingConfirm(
                 const NanBootstrappingConfirmInd& event) override {
-            parent_.callback_type_ = EVENT_BOOTSTRAPPING_CONFIRM;
             parent_.nan_bootstrapping_confirm_ind_ = event;
-            parent_.notify();
+            parent_.notify(EVENT_BOOTSTRAPPING_CONFIRM);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventBootstrappingRequest(
                 const NanBootstrappingRequestInd& event) override {
-            parent_.callback_type_ = EVENT_BOOTSTRAPPING_REQUEST;
             parent_.nan_bootstrapping_request_ind_ = event;
-            parent_.notify();
+            parent_.notify(EVENT_BOOTSTRAPPING_REQUEST);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus eventSuspensionModeChanged(
                 const NanSuspensionModeChangeInd& event) override {
-            parent_.callback_type_ = EVENT_SUSPENSION_MODE_CHANGE;
             parent_.nan_suspension_mode_change_ind_ = event;
-            parent_.notify();
+            parent_.notify(EVENT_SUSPENSION_MODE_CHANGE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyCapabilitiesResponse(
                 char16_t id, const NanStatus& status,
                 const NanCapabilities& capabilities) override {
-            parent_.callback_type_ = NOTIFY_CAPABILITIES_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
             parent_.capabilities_ = capabilities;
-            parent_.notify();
+            parent_.notify(NOTIFY_CAPABILITIES_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyConfigResponse(char16_t id, const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_CONFIG_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_CONFIG_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyCreateDataInterfaceResponse(char16_t id,
                                                                const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_CREATE_DATA_INTERFACE_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_CREATE_DATA_INTERFACE_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyDeleteDataInterfaceResponse(char16_t id,
                                                                const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_DELETE_DATA_INTERFACE_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_DELETE_DATA_INTERFACE_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyDisableResponse(char16_t id, const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_DISABLE_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_DISABLE_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyEnableResponse(char16_t id, const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_ENABLE_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_ENABLE_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyInitiateDataPathResponse(char16_t id, const NanStatus& status,
                                                             int32_t ndpInstanceId) override {
-            parent_.callback_type_ = NOTIFY_INITIATE_DATA_PATH_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
             parent_.ndp_instance_id_ = ndpInstanceId;
-            parent_.notify();
+            parent_.notify(NOTIFY_INITIATE_DATA_PATH_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyRespondToDataPathIndicationResponse(
                 char16_t id, const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyStartPublishResponse(char16_t id, const NanStatus& status,
                                                         int8_t sessionId) override {
-            parent_.callback_type_ = NOTIFY_START_PUBLISH_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
             parent_.session_id_ = sessionId;
-            parent_.notify();
+            parent_.notify(NOTIFY_START_PUBLISH_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyStartSubscribeResponse(char16_t id, const NanStatus& status,
                                                           int8_t sessionId) override {
-            parent_.callback_type_ = NOTIFY_START_SUBSCRIBE_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
             parent_.session_id_ = sessionId;
-            parent_.notify();
+            parent_.notify(NOTIFY_START_SUBSCRIBE_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyStopPublishResponse(char16_t id,
                                                        const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_STOP_PUBLISH_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_STOP_PUBLISH_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyStopSubscribeResponse(char16_t id,
                                                          const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_STOP_SUBSCRIBE_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_STOP_SUBSCRIBE_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyTerminateDataPathResponse(char16_t id,
                                                              const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_TERMINATE_DATA_PATH_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_TERMINATE_DATA_PATH_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifySuspendResponse(char16_t id, const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_SUSPEND_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_SUSPEND_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyResumeResponse(char16_t id, const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_RESUME_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_RESUME_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyTransmitFollowupResponse(char16_t id,
                                                             const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyInitiatePairingResponse(char16_t id, const NanStatus& status,
                                                            int32_t pairingInstanceId) override {
-            parent_.callback_type_ = NOTIFY_INITIATE_PAIRING_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
             parent_.pairing_instance_id_ = pairingInstanceId;
-            parent_.notify();
+            parent_.notify(NOTIFY_INITIATE_PAIRING_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyRespondToPairingIndicationResponse(
                 char16_t id, const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_RESPOND_TO_PAIRING_INDICATION_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_RESPOND_TO_PAIRING_INDICATION_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyInitiateBootstrappingResponse(
                 char16_t id, const NanStatus& status, int32_t bootstrapppingInstanceId) override {
-            parent_.callback_type_ = NOTIFY_INITIATE_BOOTSTRAPPING_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
             parent_.bootstrappping_instance_id_ = bootstrapppingInstanceId;
-            parent_.notify();
+            parent_.notify(NOTIFY_INITIATE_BOOTSTRAPPING_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyRespondToBootstrappingIndicationResponse(
                 char16_t id, const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_RESPOND_TO_BOOTSTRAPPING_INDICATION_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_RESPOND_TO_BOOTSTRAPPING_INDICATION_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
         ::ndk::ScopedAStatus notifyTerminatePairingResponse(char16_t id,
                                                             const NanStatus& status) override {
-            parent_.callback_type_ = NOTIFY_TERMINATE_PAIRING_RESPONSE;
             parent_.id_ = id;
             parent_.status_ = status;
-            parent_.notify();
+            parent_.notify(NOTIFY_TERMINATE_PAIRING_RESPONSE);
             return ndk::ScopedAStatus::ok();
         }
 
@@ -441,7 +401,7 @@
 
   protected:
     std::shared_ptr<IWifiNanIface> wifi_nan_iface_;
-    CallbackType callback_type_;
+    uint64_t callback_event_bitmap_;
     uint16_t id_;
     uint8_t session_id_;
     uint32_t ndp_instance_id_;
@@ -468,7 +428,6 @@
     // synchronization objects
     std::mutex mtx_;
     std::condition_variable cv_;
-    int count_ = 0;
 };
 
 /*
@@ -488,7 +447,7 @@
  */
 TEST_P(WifiNanIfaceAidlTest, EnableRequest_InvalidArgs) {
     uint16_t inputCmdId = 10;
-    callback_type_ = INVALID;
+    callback_event_bitmap_ = 0;
     NanEnableRequest nanEnableRequest = {};
     NanConfigRequestSupplemental nanConfigRequestSupp = {};
     auto status =
@@ -498,7 +457,7 @@
 
         // Wait for a callback.
         ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_ENABLE_RESPONSE));
-        ASSERT_EQ(NOTIFY_ENABLE_RESPONSE, callback_type_);
+        ASSERT_TRUE(receivedCallback(NOTIFY_ENABLE_RESPONSE));
         ASSERT_EQ(id_, inputCmdId);
         ASSERT_EQ(status_.status, NanStatusCode::INVALID_ARGS);
     }
@@ -509,7 +468,7 @@
  */
 TEST_P(WifiNanIfaceAidlTest, ConfigRequest_InvalidArgs) {
     uint16_t inputCmdId = 10;
-    callback_type_ = INVALID;
+    callback_event_bitmap_ = 0;
     NanConfigRequest nanConfigRequest = {};
     NanConfigRequestSupplemental nanConfigRequestSupp = {};
     auto status =
@@ -520,7 +479,7 @@
 
         // Wait for a callback.
         ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CONFIG_RESPONSE));
-        ASSERT_EQ(NOTIFY_CONFIG_RESPONSE, callback_type_);
+        ASSERT_TRUE(receivedCallback(NOTIFY_CONFIG_RESPONSE));
         ASSERT_EQ(id_, inputCmdId);
         ASSERT_EQ(status_.status, NanStatusCode::INVALID_ARGS);
     }
@@ -561,12 +520,12 @@
  */
 TEST_P(WifiNanIfaceAidlTest, NotifyCapabilitiesResponse) {
     uint16_t inputCmdId = 10;
-    callback_type_ = INVALID;
+    callback_event_bitmap_ = 0;
     EXPECT_TRUE(wifi_nan_iface_->getCapabilitiesRequest(inputCmdId).isOk());
 
     // Wait for a callback.
     ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CAPABILITIES_RESPONSE));
-    ASSERT_EQ(NOTIFY_CAPABILITIES_RESPONSE, callback_type_);
+    ASSERT_TRUE(receivedCallback(NOTIFY_CAPABILITIES_RESPONSE));
     ASSERT_EQ(id_, inputCmdId);
     ASSERT_EQ(status_.status, NanStatusCode::SUCCESS);
 
@@ -654,14 +613,14 @@
     nanConfigRequestSupp.numberOfSpatialStreamsInDiscovery = 0;
     nanConfigRequestSupp.enableDiscoveryWindowEarlyTermination = false;
 
-    callback_type_ = INVALID;
+    callback_event_bitmap_ = 0;
     auto status = wifi_nan_iface_->enableRequest(inputCmdId, req, nanConfigRequestSupp);
     if (!checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
         ASSERT_TRUE(status.isOk());
 
         // Wait for a callback.
         ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_ENABLE_RESPONSE));
-        ASSERT_EQ(NOTIFY_ENABLE_RESPONSE, callback_type_);
+        ASSERT_TRUE(receivedCallback(NOTIFY_ENABLE_RESPONSE));
         ASSERT_EQ(id_, inputCmdId);
         ASSERT_EQ(status_.status, NanStatusCode::SUCCESS);
     }
@@ -688,7 +647,7 @@
 
         // Wait for a callback.
         ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_START_PUBLISH_RESPONSE));
-        ASSERT_EQ(NOTIFY_START_PUBLISH_RESPONSE, callback_type_);
+        ASSERT_TRUE(receivedCallback(NOTIFY_START_PUBLISH_RESPONSE));
         ASSERT_EQ(id_, inputCmdId + 1);
         ASSERT_EQ(status_.status, NanStatusCode::SUCCESS);
     }
@@ -699,7 +658,7 @@
  */
 TEST_P(WifiNanIfaceAidlTest, RespondToDataPathIndicationRequest_InvalidArgs) {
     uint16_t inputCmdId = 10;
-    callback_type_ = INVALID;
+    callback_event_bitmap_ = 0;
     NanRespondToDataPathIndicationRequest nanRespondToDataPathIndicationRequest = {};
     nanRespondToDataPathIndicationRequest.ifaceName = "AwareInterfaceNameTooLong";
     auto status = wifi_nan_iface_->respondToDataPathIndicationRequest(
@@ -716,7 +675,7 @@
  */
 TEST_P(WifiNanIfaceAidlTest, InitiateDataPathRequest_InvalidArgs) {
     uint16_t inputCmdId = 10;
-    callback_type_ = INVALID;
+    callback_event_bitmap_ = 0;
     NanInitiateDataPathRequest nanInitiateDataPathRequest = {};
     nanInitiateDataPathRequest.ifaceName = "AwareInterfaceNameTooLong";
     auto status = wifi_nan_iface_->initiateDataPathRequest(inputCmdId, nanInitiateDataPathRequest);
diff --git a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
index f12d873..1ea1237 100644
--- a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <cctype>
 #include <vector>
 
 #include <VtsCoreUtil.h>
@@ -68,6 +69,50 @@
 
     std::shared_ptr<IWifiStaIface> wifi_sta_iface_;
 
+    // Checks if the MdnsOffloadManagerService is installed.
+    bool isMdnsOffloadServicePresent() {
+        int status =
+                // --query-flags MATCH_SYSTEM_ONLY(1048576) will only return matched service
+                // installed on system or system_ext partition. The MdnsOffloadManagerService should
+                // be installed on system_ext partition.
+                // NOLINTNEXTLINE(cert-env33-c)
+                system("pm query-services --query-flags 1048576"
+                       " com.android.tv.mdnsoffloadmanager/"
+                       "com.android.tv.mdnsoffloadmanager.MdnsOffloadManagerService"
+                       " | egrep -q mdnsoffloadmanager");
+        return status == 0;
+    }
+
+    // Detected panel TV device by using ro.oem.key1 property.
+    // https://docs.partner.android.com/tv/build/platform/props-vars/ro-oem-key1
+    bool isPanelTvDevice() {
+        const std::string oem_key1 = getPropertyString("ro.oem.key1");
+        if (oem_key1.size() < 9) {
+            return false;
+        }
+        if (oem_key1.substr(0, 3) != "ATV") {
+            return false;
+        }
+        const std::string psz_string = oem_key1.substr(6, 3);
+        // If PSZ string contains non digit, then it is not a panel TV device.
+        for (char ch : psz_string) {
+            if (!isdigit(ch)) {
+                return false;
+            }
+        }
+        // If PSZ is "000", then it is not a panel TV device.
+        if (psz_string == "000") {
+            return false;
+        }
+        return true;
+    }
+
+    std::string getPropertyString(const char* property_name) {
+        char property_string_raw_bytes[PROPERTY_VALUE_MAX] = {};
+        int len = property_get(property_name, property_string_raw_bytes, "");
+        return std::string(property_string_raw_bytes, len);
+    }
+
   private:
     const char* getInstanceName() { return GetParam().c_str(); }
 };
@@ -99,6 +144,11 @@
  */
 // @VsrTest = 5.3.12
 TEST_P(WifiStaIfaceAidlTest, CheckApfIsSupported) {
+    // Flat panel TV devices that support MDNS offload do not have to implement APF if the WiFi
+    // chipset does not have sufficient RAM to do so.
+    if (isPanelTvDevice() && isMdnsOffloadServicePresent()) {
+        GTEST_SKIP() << "Panel TV supports mDNS offload. It is not required to support APF";
+    }
     int vendor_api_level = property_get_int32("ro.vendor.api_level", 0);
     // Before VSR 14, APF support is optional.
     if (vendor_api_level < __ANDROID_API_U__) {
diff --git a/wifi/apex/Android.bp b/wifi/apex/Android.bp
index f8ba5c4..f8c8e6f 100644
--- a/wifi/apex/Android.bp
+++ b/wifi/apex/Android.bp
@@ -2,17 +2,6 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-apex_key {
-    name: "com.android.hardware.wifi.key",
-    public_key: "com.android.hardware.wifi.avbpubkey",
-    private_key: "com.android.hardware.wifi.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.wifi.certificate",
-    certificate: "com.android.hardware.wifi",
-}
-
 genrule {
     name: "gen-android.hardware.wifi.rc",
     srcs: [":default-android.hardware.wifi-service.rc"],
@@ -36,12 +25,12 @@
 apex {
     name: "com.android.hardware.wifi",
     manifest: "apex_manifest.json",
-    key: "com.android.hardware.wifi.key",
-    certificate: ":com.android.hardware.wifi.certificate",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
     file_contexts: "file_contexts",
-    use_vndk_as_stable: true,
     updatable: false,
-    soc_specific: true,
+    vendor: true,
+
     binaries: [
         "android.hardware.wifi-service",
     ],
diff --git a/wifi/apex/com.android.hardware.wifi.avbpubkey b/wifi/apex/com.android.hardware.wifi.avbpubkey
deleted file mode 100644
index 63fba77..0000000
--- a/wifi/apex/com.android.hardware.wifi.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/wifi/apex/com.android.hardware.wifi.pem b/wifi/apex/com.android.hardware.wifi.pem
deleted file mode 100644
index 9e589ac..0000000
--- a/wifi/apex/com.android.hardware.wifi.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-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
-etEvMk8bJ4u7X89NWW/i2J+kQiDQg819
------END PRIVATE KEY-----
diff --git a/wifi/apex/com.android.hardware.wifi.pk8 b/wifi/apex/com.android.hardware.wifi.pk8
deleted file mode 100644
index f4481bf..0000000
--- a/wifi/apex/com.android.hardware.wifi.pk8
+++ /dev/null
Binary files differ
diff --git a/wifi/apex/com.android.hardware.wifi.x509.pem b/wifi/apex/com.android.hardware.wifi.x509.pem
deleted file mode 100644
index c942e71..0000000
--- a/wifi/apex/com.android.hardware.wifi.x509.pem
+++ /dev/null
@@ -1,36 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGOzCCBCOgAwIBAgIUIEueuBFEoCFmLyEvXDsKVuZeH0EwDQYJKoZIhvcNAQEL
-BQAwgasxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
-DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
-b2lkMScwJQYDVQQDDB5jb20uYW5kcm9pZC5oYXJkd2FyZS53aWZpLmFwZXgxIjAg
-BgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5kcm9pZC5jb20wIBcNMjIxMDA2MTY1MDQy
-WhgPNDc2MDA5MDExNjUwNDJaMIGrMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2Fs
-aWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9p
-ZDEQMA4GA1UECwwHQW5kcm9pZDEnMCUGA1UEAwweY29tLmFuZHJvaWQuaGFyZHdh
-cmUud2lmaS5hcGV4MSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
-MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAo4N23iL0J42qG2lt4ysD
-t6XxAKdi4sTWB6ZjFWerBm11s3yLr1KBZV82z3j2o7+EOaWa/91Mgc+aoiGYUa1f
-IweugKTrnRmrzOvtq/Wp5PGqSxsmLPPvH3wyEB/CMgAn0pqDf0WyCWJ2kAlcCkmy
-qVNFupkGFyIE6gkoc+AmJGbSTquDlL07R/8XYDicqrcgeqy9ZaCJ5FLfmbnnRb2A
-vm4Un7e5dFz5+dPaOJXf4AOMUSPUd7fuBliGYFLzcZnYQbzMktXa4XnPuSlmerwy
-EwY767L2bjRjaSgPb0Js13gZ4S4ZHZe07AV7HPlt/EzbxV/jtMgHl4xn5p0WhVnK
-MPtLsO/e7FkDPAKpT02sgUK6pVKqgBGOWm27tmTB09lscMLQeVFqwpoFq2zMUrDn
-ipDFMWRBeLrEDKx41zF3gqdPmP+SMkQYJu4OATIXOndIeo7AN9iE+N6snHkckNyE
-saCwmnzyhVAbMn/epfIQZz3zcyljA9yfOpv5jctN4es+3i0htDnoNO9ij4M5fxuP
-jtNAP3EA61nKZ5+Js0/MMQKrfwCLogPl/4vCNuuGT2rhCkhq1CLYXmb9ghvVzcPe
-BOGXNDKdB+aUTxrQUOYlHf0cRDHdU6cchrz9+QhR7t9dlibtiyCZE34xgR3klmyz
-XJ3M1r/QRihjARH7exrrwiUCAwEAAaNTMFEwHQYDVR0OBBYEFGN9tMk+4SDk7twk
-MrLjM+nRxGDJMB8GA1UdIwQYMBaAFGN9tMk+4SDk7twkMrLjM+nRxGDJMA8GA1Ud
-EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAHoTfVBRG0rVE7gkV526gwR5
-/3mXyYA57lKJhZ21fu2qfTE6WYj4DsOTZKrPIAUFv/SnzZ6Rvv7W81XV5M/1m+5R
-/1wYvWwm3FBOvvt4VDUiel0Zfc9+nwynjz1seYdXU8fNIOzBcr9hutkYdRZDkNpc
-Zcl4NG04TzyedkQ/0SyHnygmq4ZY9OUEvrNaWBFHzw2SQhYvHh8jUrqpPvoJz0Px
-avKI8bOgXTJRJ+Pk7hjXDFQY/fbE0RGivorPMLs+XHaEIb+YPyXsX4OZwowG5KL8
-txyvUsH+qZToytdPk4LCuwYBobBlr+AAg7pxOtbDW1ITDhQ9n05UFK2iUwsJecgg
-VDA0K3GuCjmGVmkw7SFRYfToCyGWah8sQCUMCCcsof7gS+dMxuWeee+sRxRJcJY+
-xR2uySe8g4ohwNjQ0zLQv7PZOKQh91yEWxRXmhPYVpiVAjpSD2zH7Vd6CJ9xji//
-5S1UrxWwQ5igvu8v5veqNAW7uXGXADnxL69HVGTLm0XDIUUOAUIG8waiVkYUo3UU
-AzAFbF7ewYMKdg7ylUYcTaMRIsKYW/3/1t3NJv2z99W4V/p8e1kRCeWMPB5C+/Lo
-b/hSWj1NF9AJ30ukBndMh6bRprq+G5NLV6OaoCLp606CMdXdT8uw9lYCt7DbQHG9
-Hw3iw61svpUwcaWfN1hI
------END CERTIFICATE-----
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
index 3ae9b39..4c452fb 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
@@ -41,10 +41,9 @@
 using ::android::wifi_system::HostapdManager;
 using ::android::wifi_system::SupplicantManager;
 
-namespace {
 // Helper function to initialize the driver and firmware to AP mode
 // using the vendor HAL HIDL interface.
-void initilializeDriverAndFirmware(const std::string& wifi_instance_name) {
+void initializeDriverAndFirmware(const std::string& wifi_instance_name) {
     if (getWifi(wifi_instance_name) != nullptr) {
         sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
         ChipModeId mode_id;
@@ -57,21 +56,20 @@
 
 // Helper function to deinitialize the driver and firmware
 // using the vendor HAL HIDL interface.
-void deInitilializeDriverAndFirmware(const std::string& wifi_instance_name) {
+void deInitializeDriverAndFirmware(const std::string& wifi_instance_name) {
     if (getWifi(wifi_instance_name) != nullptr) {
         stopWifi(wifi_instance_name);
     } else {
         LOG(WARNING) << __func__ << ": Vendor HAL not supported";
     }
 }
-}  // namespace
 
 void stopSupplicantIfNeeded(const std::string& instance_name) {
     SupplicantManager supplicant_manager;
     if (supplicant_manager.IsSupplicantRunning()) {
         LOG(INFO) << "Supplicant is running, stop supplicant first.";
         ASSERT_TRUE(supplicant_manager.StopSupplicant());
-        deInitilializeDriverAndFirmware(instance_name);
+        deInitializeDriverAndFirmware(instance_name);
         ASSERT_FALSE(supplicant_manager.IsSupplicantRunning());
     }
 }
@@ -80,13 +78,13 @@
     HostapdManager hostapd_manager;
 
     ASSERT_TRUE(hostapd_manager.StopHostapd());
-    deInitilializeDriverAndFirmware(instance_name);
+    deInitializeDriverAndFirmware(instance_name);
 }
 
 void startHostapdAndWaitForHidlService(
     const std::string& wifi_instance_name,
     const std::string& hostapd_instance_name) {
-    initilializeDriverAndFirmware(wifi_instance_name);
+    initializeDriverAndFirmware(wifi_instance_name);
 
     HostapdManager hostapd_manager;
     ASSERT_TRUE(hostapd_manager.StartHostapd());
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
index ea7c112..aa34c9a 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
@@ -36,5 +36,9 @@
 
 bool is_1_1(const android::sp<android::hardware::wifi::hostapd::V1_0::IHostapd>&
                 hostapd);
+// Used to initialize/deinitialize the driver and firmware at the
+// beginning and end of each test.
+void initializeDriverAndFirmware(const std::string& wifi_instance_name);
+void deInitializeDriverAndFirmware(const std::string& wifi_instance_name);
 
 #endif /* HOSTAPD_HIDL_TEST_UTILS_H */
diff --git a/wifi/hostapd/aidl/vts/functional/Android.bp b/wifi/hostapd/aidl/vts/functional/Android.bp
index 33318a4..ff35056 100644
--- a/wifi/hostapd/aidl/vts/functional/Android.bp
+++ b/wifi/hostapd/aidl/vts/functional/Android.bp
@@ -37,6 +37,7 @@
         "android.hardware.wifi@1.5",
         "android.hardware.wifi@1.6",
         "android.hardware.wifi-V1-ndk",
+        "libwifi-system",
         "libwifi-system-iface",
         "VtsHalWifiTargetTestUtil",
     ],
diff --git a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
index efd1538..137537d 100644
--- a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
+++ b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
@@ -32,6 +32,7 @@
 #include <wifi_hidl_test_utils_1_5.h>
 #include <wifi_hidl_test_utils_1_6.h>
 
+#include "hostapd_test_utils.h"
 #include "wifi_aidl_test_utils.h"
 
 using aidl::android::hardware::wifi::hostapd::BandMask;
@@ -56,10 +57,7 @@
 const int kIfaceChannel = 6;
 const int kIfaceInvalidChannel = 567;
 const std::vector<uint8_t> kTestZeroMacAddr(6, 0x0);
-const Ieee80211ReasonCode kTestDisconnectReasonCode =
-    Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED;
-const std::string kWifiAidlInstanceNameStr = std::string() + IWifi::descriptor + "/default";
-const char* kWifiAidlInstanceName = kWifiAidlInstanceNameStr.c_str();
+const Ieee80211ReasonCode kTestDisconnectReasonCode = Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED;
 
 inline BandMask operator|(BandMask a, BandMask b) {
     return static_cast<BandMask>(static_cast<int32_t>(a) |
@@ -70,10 +68,13 @@
 class HostapdAidl : public testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
-        hostapd = IHostapd::fromBinder(ndk::SpAIBinder(
-            AServiceManager_waitForService(GetParam().c_str())));
+        disableHalsAndFramework();
+        initializeHostapdAndVendorHal(GetParam());
+
+        hostapd = getHostapd(GetParam());
         ASSERT_NE(hostapd, nullptr);
         EXPECT_TRUE(hostapd->setDebugParams(DebugLevel::EXCESSIVE).isOk());
+
         isAcsSupport = testing::checkSubstringInCommandOutput(
             "/system/bin/cmd wifi get-softap-supported-features",
             "wifi_softap_acs_supported");
@@ -81,81 +82,23 @@
             "/system/bin/cmd wifi get-softap-supported-features",
             "wifi_softap_wpa3_sae_supported");
         isBridgedSupport = testing::checkSubstringInCommandOutput(
-            "/system/bin/cmd wifi get-softap-supported-features",
-            "wifi_softap_bridged_ap_supported");
-        if (!isAidlServiceAvailable(kWifiAidlInstanceName)) {
-            const std::vector<std::string> instances = android::hardware::getAllHalInstanceNames(
-                    ::android::hardware::wifi::V1_0::IWifi::descriptor);
-            EXPECT_NE(0, instances.size());
-            wifiHidlInstanceName = instances[0];
-        }
+                "/system/bin/cmd wifi get-softap-supported-features",
+                "wifi_softap_bridged_ap_supported");
     }
 
     virtual void TearDown() override {
-        stopVendorHal();
         hostapd->terminate();
         //  Wait 3 seconds to allow terminate to complete
         sleep(3);
+        stopHostapdAndVendorHal();
+        startWifiFramework();
     }
 
     std::shared_ptr<IHostapd> hostapd;
-    std::string wifiHidlInstanceName;
     bool isAcsSupport;
     bool isWpa3SaeSupport;
     bool isBridgedSupport;
 
-    void stopVendorHal() {
-        if (isAidlServiceAvailable(kWifiAidlInstanceName)) {
-            // HIDL and AIDL versions of getWifi() take different arguments
-            // i.e. const char* vs string
-            if (getWifi(kWifiAidlInstanceName) != nullptr) {
-                stopWifiService(kWifiAidlInstanceName);
-            }
-        } else {
-            if (getWifi(wifiHidlInstanceName) != nullptr) {
-                stopWifi(wifiHidlInstanceName);
-            }
-        }
-    }
-
-    std::string setupApIfaceAndGetName(bool isBridged) {
-        if (isAidlServiceAvailable(kWifiAidlInstanceName)) {
-            return setupApIfaceAndGetNameAidl(isBridged);
-        } else {
-            return setupApIfaceAndGetNameHidl(isBridged);
-        }
-    }
-
-    std::string setupApIfaceAndGetNameAidl(bool isBridged) {
-        std::shared_ptr<IWifiApIface> wifi_ap_iface;
-        if (isBridged) {
-            wifi_ap_iface = getBridgedWifiApIface(kWifiAidlInstanceName);
-        } else {
-            wifi_ap_iface = getWifiApIface(kWifiAidlInstanceName);
-        }
-        EXPECT_NE(nullptr, wifi_ap_iface.get());
-
-        std::string ap_iface_name;
-        auto status = wifi_ap_iface->getName(&ap_iface_name);
-        EXPECT_TRUE(status.isOk());
-        return ap_iface_name;
-    }
-
-    std::string setupApIfaceAndGetNameHidl(bool isBridged) {
-        android::sp<::android::hardware::wifi::V1_0::IWifiApIface> wifi_ap_iface;
-        if (isBridged) {
-            wifi_ap_iface = getBridgedWifiApIface_1_6(wifiHidlInstanceName);
-        } else {
-            wifi_ap_iface = getWifiApIface_1_5(wifiHidlInstanceName);
-        }
-        EXPECT_NE(nullptr, wifi_ap_iface.get());
-
-        const auto& status_and_name = HIDL_INVOKE(wifi_ap_iface, getName);
-        EXPECT_EQ(android::hardware::wifi::V1_0::WifiStatusCode::SUCCESS,
-                  status_and_name.first.code);
-        return status_and_name.second;
-    }
-
     IfaceParams getIfaceParamsWithoutAcs(std::string iface_name) {
         IfaceParams iface_params;
         ChannelParams channelParams;
diff --git a/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h b/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h
new file mode 100644
index 0000000..93540b2
--- /dev/null
+++ b/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/wifi/IWifi.h>
+#include <android-base/logging.h>
+
+#include "wifi_aidl_test_utils.h"
+
+namespace {
+
+const std::string kWifiInstanceNameStr = std::string() + IWifi::descriptor + "/default";
+const char* kWifiInstanceName = kWifiInstanceNameStr.c_str();
+
+}  // namespace
+
+namespace HostapdAidlTestUtils {
+
+bool useAidlService() {
+    return isAidlServiceAvailable(kWifiInstanceName);
+}
+
+void startAndConfigureVendorHal() {
+    if (getWifi(kWifiInstanceName) != nullptr) {
+        std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(kWifiInstanceName);
+        int mode_id;
+        EXPECT_TRUE(configureChipToSupportConcurrencyType(wifi_chip, IfaceConcurrencyType::AP,
+                                                          &mode_id));
+    } else {
+        LOG(ERROR) << "Unable to initialize Vendor HAL";
+    }
+}
+
+void stopVendorHal() {
+    if (getWifi(kWifiInstanceName) != nullptr) {
+        stopWifiService(kWifiInstanceName);
+    } else {
+        LOG(ERROR) << "Unable to stop Vendor HAL";
+    }
+}
+
+std::string setupApIfaceAndGetName(bool isBridged) {
+    std::shared_ptr<IWifiApIface> wifi_ap_iface;
+    if (isBridged) {
+        wifi_ap_iface = getBridgedWifiApIface(kWifiInstanceName);
+    } else {
+        wifi_ap_iface = getWifiApIface(kWifiInstanceName);
+    }
+
+    EXPECT_TRUE(wifi_ap_iface.get() != nullptr);
+    if (!wifi_ap_iface.get()) {
+        LOG(ERROR) << "Unable to create iface. isBridged=" << isBridged;
+        return "";
+    }
+
+    std::string ap_iface_name;
+    auto status = wifi_ap_iface->getName(&ap_iface_name);
+    EXPECT_TRUE(status.isOk());
+    if (!status.isOk()) {
+        LOG(ERROR) << "Unable to retrieve iface name. isBridged=" << isBridged;
+        return "";
+    }
+    return ap_iface_name;
+}
+
+}  // namespace HostapdAidlTestUtils
diff --git a/wifi/hostapd/aidl/vts/functional/hostapd_legacy_test_utils.h b/wifi/hostapd/aidl/vts/functional/hostapd_legacy_test_utils.h
new file mode 100644
index 0000000..fb59dc2
--- /dev/null
+++ b/wifi/hostapd/aidl/vts/functional/hostapd_legacy_test_utils.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 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 <android-base/logging.h>
+
+#include "hostapd_hidl_test_utils.h"
+#include "wifi_hidl_test_utils.h"
+
+using ::android::hardware::wifi::V1_0::WifiStatus;
+
+namespace {
+
+std::string getWifiInstanceName() {
+    const std::vector<std::string> instances = android::hardware::getAllHalInstanceNames(
+            ::android::hardware::wifi::V1_0::IWifi::descriptor);
+    EXPECT_NE(0, instances.size());
+    return instances.size() != 0 ? instances[0] : "";
+}
+
+}  // namespace
+
+namespace HostapdLegacyTestUtils {
+
+void startAndConfigureVendorHal() {
+    initializeDriverAndFirmware(getWifiInstanceName());
+}
+
+void stopVendorHal() {
+    deInitializeDriverAndFirmware(getWifiInstanceName());
+}
+
+std::string setupApIfaceAndGetName(bool isBridged) {
+    android::sp<::android::hardware::wifi::V1_0::IWifiApIface> wifi_ap_iface;
+    if (isBridged) {
+        wifi_ap_iface = getBridgedWifiApIface_1_6(getWifiInstanceName());
+    } else {
+        wifi_ap_iface = getWifiApIface_1_5(getWifiInstanceName());
+    }
+
+    EXPECT_TRUE(wifi_ap_iface.get() != nullptr);
+    if (!wifi_ap_iface.get()) {
+        LOG(ERROR) << "Unable to create iface. isBridged=" << isBridged;
+        return "";
+    }
+
+    const auto& status_and_name = HIDL_INVOKE(wifi_ap_iface, getName);
+    EXPECT_TRUE(status_and_name.first.code ==
+                android::hardware::wifi::V1_0::WifiStatusCode::SUCCESS);
+    if (status_and_name.first.code != android::hardware::wifi::V1_0::WifiStatusCode::SUCCESS) {
+        LOG(ERROR) << "Unable to retrieve iface name. isBridged=" << isBridged;
+        return "";
+    }
+    return status_and_name.second;
+}
+
+}  // namespace HostapdLegacyTestUtils
diff --git a/wifi/hostapd/aidl/vts/functional/hostapd_test_utils.h b/wifi/hostapd/aidl/vts/functional/hostapd_test_utils.h
new file mode 100644
index 0000000..50a38d3
--- /dev/null
+++ b/wifi/hostapd/aidl/vts/functional/hostapd_test_utils.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/wifi/hostapd/BnHostapd.h>
+#include <android-base/logging.h>
+#include <wifi_system/hostapd_manager.h>
+#include <wifi_system/supplicant_manager.h>
+
+#include "hostapd_aidl_test_utils.h"
+#include "hostapd_legacy_test_utils.h"
+
+using aidl::android::hardware::wifi::hostapd::IHostapd;
+using android::wifi_system::HostapdManager;
+using android::wifi_system::SupplicantManager;
+
+namespace {
+
+void startAndConfigureVendorHal() {
+    if (HostapdAidlTestUtils::useAidlService()) {
+        HostapdAidlTestUtils::startAndConfigureVendorHal();
+    } else {
+        HostapdLegacyTestUtils::startAndConfigureVendorHal();
+    }
+}
+
+void stopVendorHal() {
+    if (HostapdAidlTestUtils::useAidlService()) {
+        HostapdAidlTestUtils::stopVendorHal();
+    } else {
+        HostapdLegacyTestUtils::stopVendorHal();
+    }
+}
+
+void stopHostapd() {
+    HostapdManager hostapd_manager;
+    ASSERT_TRUE(hostapd_manager.StopHostapd());
+}
+
+void waitForSupplicantState(bool enable) {
+    SupplicantManager supplicant_manager;
+    int count = 50;  // wait at most 5 seconds
+    while (count-- > 0) {
+        if (supplicant_manager.IsSupplicantRunning() == enable) {
+            return;
+        }
+        usleep(100000);  // 100 ms
+    }
+    LOG(ERROR) << "Unable to " << (enable ? "start" : "stop") << " supplicant";
+}
+
+void toggleWifiFrameworkAndScan(bool enable) {
+    if (enable) {
+        std::system("svc wifi enable");
+        std::system("cmd wifi set-scan-always-available enabled");
+        waitForSupplicantState(true);
+    } else {
+        std::system("svc wifi disable");
+        std::system("cmd wifi set-scan-always-available disabled");
+        waitForSupplicantState(false);
+    }
+}
+
+}  // namespace
+
+std::shared_ptr<IHostapd> getHostapd(const std::string& hostapd_instance_name) {
+    return IHostapd::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(hostapd_instance_name.c_str())));
+}
+
+/**
+ * Disable the Wifi framework, hostapd, and vendor HAL.
+ *
+ * Note: The framework should be disabled to avoid having
+ *       any other clients to the HALs during testing.
+ */
+void disableHalsAndFramework() {
+    toggleWifiFrameworkAndScan(false);
+    stopHostapd();
+    stopVendorHal();
+
+    // Wait for the services to stop.
+    sleep(3);
+}
+
+void initializeHostapdAndVendorHal(const std::string& hostapd_instance_name) {
+    startAndConfigureVendorHal();
+    HostapdManager hostapd_manager;
+    ASSERT_TRUE(hostapd_manager.StartHostapd());
+    getHostapd(hostapd_instance_name);
+}
+
+void stopHostapdAndVendorHal() {
+    stopHostapd();
+    stopVendorHal();
+}
+
+void startWifiFramework() {
+    toggleWifiFrameworkAndScan(true);
+}
+
+std::string setupApIfaceAndGetName(bool isBridged) {
+    if (HostapdAidlTestUtils::useAidlService()) {
+        return HostapdAidlTestUtils::setupApIfaceAndGetName(isBridged);
+    } else {
+        return HostapdLegacyTestUtils::setupApIfaceAndGetName(isBridged);
+    }
+}