Merge "Added access field to VehicleAreaConfig.aidl" into main
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 5a009fe..0ab990a 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -34,6 +34,7 @@
     name: "android.hardware.audio.common",
     defaults: [
         "android.hardware.audio_defaults",
+        "latest_android_media_audio_common_types_import_interface",
     ],
     srcs: [
         "android/hardware/audio/common/AudioOffloadMetadata.aidl",
@@ -42,10 +43,7 @@
         "android/hardware/audio/common/SinkMetadata.aidl",
         "android/hardware/audio/common/SourceMetadata.aidl",
     ],
-    frozen: true,
-    imports: [
-        "android.media.audio.common.types-V2",
-    ],
+    frozen: false,
     backend: {
         cpp: {
             enabled: true,
@@ -83,7 +81,7 @@
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_audio_common = "android.hardware.audio.common-V2"
+latest_android_hardware_audio_common = "android.hardware.audio.common-V3"
 
 // Modules that depend on android.hardware.audio.common directly can include
 // the following cc_defaults to avoid explicitly managing dependency versions
@@ -109,10 +107,21 @@
     ],
 }
 
+aidl_interface_defaults {
+    name: "latest_android_hardware_audio_common_import_interface",
+    imports: [
+        latest_android_hardware_audio_common,
+    ],
+}
+
 aidl_interface {
     name: "android.hardware.audio.core",
     defaults: [
         "android.hardware.audio_defaults",
+        "latest_android_hardware_audio_common_import_interface",
+        "latest_android_hardware_audio_core_sounddose_import_interface",
+        "latest_android_hardware_audio_effect_import_interface",
+        "latest_android_media_audio_common_types_import_interface",
     ],
     srcs: [
         "android/hardware/audio/core/AudioPatch.aidl",
@@ -137,10 +146,6 @@
     imports: [
         "android.hardware.common-V2",
         "android.hardware.common.fmq-V1",
-        "android.hardware.audio.common-V2",
-        "android.hardware.audio.core.sounddose-V1",
-        "android.hardware.audio.effect-V1",
-        "android.media.audio.common.types-V2",
     ],
     backend: {
         // The C++ backend is disabled transitively due to use of FMQ.
@@ -167,11 +172,11 @@
         // IMPORTANT: Update latest_android_hardware_audio_core every time you
         // add the latest frozen version to versions_with_info
     ],
-    frozen: true,
+    frozen: false,
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_audio_core = "android.hardware.audio.core-V1"
+latest_android_hardware_audio_core = "android.hardware.audio.core-V2"
 
 // Modules that depend on android.hardware.audio.core directly can include
 // the following cc_defaults to avoid explicitly managing dependency versions
@@ -190,18 +195,23 @@
     ],
 }
 
+aidl_interface_defaults {
+    name: "latest_android_hardware_audio_core_import_interface",
+    imports: [
+        latest_android_hardware_audio_core,
+    ],
+}
+
 // Used for the standalone sounddose HAL
 aidl_interface {
     name: "android.hardware.audio.core.sounddose",
     defaults: [
         "android.hardware.audio_defaults",
+        "latest_android_media_audio_common_types_import_interface",
     ],
     srcs: [
         "android/hardware/audio/core/sounddose/ISoundDose.aidl",
     ],
-    imports: [
-        "android.media.audio.common.types-V2",
-    ],
     backend: {
         // The C++ backend is disabled transitively due to use of FMQ by the core HAL.
         cpp: {
@@ -220,11 +230,11 @@
         // IMPORTANT: Update latest_android_hardware_audio_core_sounddose every time you
         // add the latest frozen version to versions_with_info
     ],
-    frozen: true,
+    frozen: false,
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_audio_core_sounddose = "android.hardware.audio.core.sounddose-V1"
+latest_android_hardware_audio_core_sounddose = "android.hardware.audio.core.sounddose-V2"
 
 // Modules that depend on android.hardware.audio.core.sounddose directly can include
 // the following cc_defaults to avoid explicitly managing dependency versions
@@ -237,16 +247,32 @@
 }
 
 cc_defaults {
+    name: "latest_android_hardware_audio_core_sounddose_ndk_export_shared_lib_header",
+    export_shared_lib_headers: [
+        latest_android_hardware_audio_core_sounddose + "-ndk",
+    ],
+}
+
+cc_defaults {
     name: "latest_android_hardware_audio_core_sounddose_ndk_static",
     static_libs: [
         latest_android_hardware_audio_core_sounddose + "-ndk",
     ],
 }
 
+aidl_interface_defaults {
+    name: "latest_android_hardware_audio_core_sounddose_import_interface",
+    imports: [
+        latest_android_hardware_audio_core_sounddose,
+    ],
+}
+
 aidl_interface {
     name: "android.hardware.audio.effect",
     defaults: [
         "android.hardware.audio_defaults",
+        "latest_android_hardware_audio_common_import_interface",
+        "latest_android_media_audio_common_types_import_interface",
     ],
     srcs: [
         "android/hardware/audio/effect/AcousticEchoCanceler.aidl",
@@ -280,8 +306,6 @@
     imports: [
         "android.hardware.common-V2",
         "android.hardware.common.fmq-V1",
-        "android.hardware.audio.common-V2",
-        "android.media.audio.common.types-V2",
     ],
     backend: {
         // The C++ backend is disabled transitively due to use of FMQ.
@@ -303,11 +327,11 @@
             ],
         },
     ],
-    frozen: true,
+    frozen: false,
 
 }
 
-latest_android_hardware_audio_effect = "android.hardware.audio.effect-V1"
+latest_android_hardware_audio_effect = "android.hardware.audio.effect-V2"
 
 cc_defaults {
     name: "latest_android_hardware_audio_effect_ndk_shared",
@@ -322,3 +346,10 @@
         latest_android_hardware_audio_effect + "-ndk",
     ],
 }
+
+aidl_interface_defaults {
+    name: "latest_android_hardware_audio_effect_import_interface",
+    imports: [
+        latest_android_hardware_audio_effect,
+    ],
+}
diff --git a/audio/aidl/common/Android.bp b/audio/aidl/common/Android.bp
index 4c6a74e..85ece3b 100644
--- a/audio/aidl/common/Android.bp
+++ b/audio/aidl/common/Android.bp
@@ -45,8 +45,8 @@
     name: "libaudioaidlranges",
     host_supported: true,
     vendor_available: true,
-    static_libs: [
-        "android.hardware.audio.effect-V1-ndk",
+    defaults: [
+        "latest_android_hardware_audio_effect_ndk_shared",
     ],
     export_include_dirs: ["include"],
     header_libs: ["libaudioaidl_headers"],
@@ -59,8 +59,10 @@
     name: "libaudioaidlcommon_test",
     host_supported: true,
     vendor_available: true,
+    defaults: [
+        "latest_android_media_audio_common_types_ndk_static",
+    ],
     static_libs: [
-        "android.media.audio.common.types-V1-ndk",
         "libaudioaidlcommon",
     ],
     shared_libs: [
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index af12e75..de247f1 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 {
@@ -72,6 +78,7 @@
         "latest_android_media_audio_common_types_ndk_shared",
         "latest_android_hardware_audio_core_ndk_shared",
         "latest_android_hardware_audio_core_sounddose_ndk_shared",
+        "latest_android_hardware_bluetooth_audio_ndk_shared",
     ],
     export_include_dirs: ["include"],
     srcs: [
@@ -87,6 +94,7 @@
         "Stream.cpp",
         "StreamSwitcher.cpp",
         "Telephony.cpp",
+        "XsdcConversion.cpp",
         "alsa/Mixer.cpp",
         "alsa/ModuleAlsa.cpp",
         "alsa/StreamAlsa.cpp",
@@ -118,7 +126,6 @@
         "audio_policy_engine_configuration_aidl_default",
     ],
     shared_libs: [
-        "android.hardware.bluetooth.audio-V3-ndk",
         "libaudio_aidl_conversion_common_ndk",
         "libaudioutils",
         "libaudioutils_nonvndk",
@@ -147,15 +154,15 @@
     vintf_fragments: ["android.hardware.audio.service-aidl.xml"],
     defaults: [
         "aidlaudioservice_defaults",
-        "latest_android_media_audio_common_types_ndk_shared",
         "latest_android_hardware_audio_core_sounddose_ndk_shared",
         "latest_android_hardware_audio_core_ndk_shared",
+        "latest_android_hardware_bluetooth_audio_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
     ],
     static_libs: [
         "libaudioserviceexampleimpl",
     ],
     shared_libs: [
-        "android.hardware.bluetooth.audio-V3-ndk",
         "libaudioutils_nonvndk",
         "libaudio_aidl_conversion_common_ndk",
         "libbluetooth_audio_session_aidl",
@@ -187,6 +194,7 @@
         "libbase",
         "libbinder_ndk",
         "libcutils",
+        "libfmq",
         "libmedia_helper",
         "libstagefright_foundation",
         "libutils",
@@ -199,9 +207,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 3c3dadb..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 {
 
@@ -135,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:
@@ -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);
@@ -677,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 9fc99d4..1ec171a 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;
@@ -132,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:
@@ -168,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});
 }
@@ -308,6 +330,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;
@@ -321,26 +359,8 @@
     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());
 }
 
 std::vector<AudioRoute*> Module::getAudioRoutesForAudioPortImpl(int32_t portId) {
@@ -355,7 +375,7 @@
     return result;
 }
 
-internal::Configuration& Module::getConfig() {
+Module::Configuration& Module::getConfig() {
     if (!mConfig) {
         mConfig = std::move(initializeConfig());
     }
@@ -802,7 +822,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(
@@ -1236,7 +1256,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();
 }
@@ -1515,6 +1535,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.effect.service-aidl.xml b/audio/aidl/default/android.hardware.audio.effect.service-aidl.xml
index fdc53a3..05a825d 100644
--- a/audio/aidl/default/android.hardware.audio.effect.service-aidl.xml
+++ b/audio/aidl/default/android.hardware.audio.effect.service-aidl.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
   <hal format="aidl">
     <name>android.hardware.audio.effect</name>
-    <version>1</version>
+    <version>2</version>
     <fqname>IFactory/default</fqname>
   </hal>
 </manifest>
diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.xml b/audio/aidl/default/android.hardware.audio.service-aidl.xml
index 9db6061..2a51876 100644
--- a/audio/aidl/default/android.hardware.audio.service-aidl.xml
+++ b/audio/aidl/default/android.hardware.audio.service-aidl.xml
@@ -1,16 +1,27 @@
 <manifest version="1.0" type="device">
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
-    <version>1</version>
+    <version>2</version>
     <fqname>IModule/default</fqname>
   </hal>
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
-    <version>1</version>
+    <version>2</version>
     <fqname>IModule/r_submix</fqname>
   </hal>
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
+    <version>2</version>
+    <fqname>IModule/bluetooth</fqname>
+  </hal>
+  <hal format="aidl">
+    <name>android.hardware.audio.core</name>
+    <version>2</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>
@@ -19,14 +30,5 @@
     <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">
-    <name>android.hardware.audio.core</name>
-    <version>1</version>
-    <fqname>IConfig/default</fqname>
-  </hal>
+  -->
 </manifest>
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 f407e25..d92d54b 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();
@@ -204,7 +223,7 @@
             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; }
@@ -215,6 +234,7 @@
     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 526a809..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;
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/sounddose/Android.bp b/audio/aidl/sounddose/Android.bp
index 6f2f790..c65e4ff 100644
--- a/audio/aidl/sounddose/Android.bp
+++ b/audio/aidl/sounddose/Android.bp
@@ -52,11 +52,11 @@
         // IMPORTANT: Update latest_android_hardware_audio_sounddose every time you
         // add the latest frozen version to versions_with_info
     ],
-    frozen: true,
+    frozen: false,
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_audio_sounddose = "android.hardware.audio.sounddose-V1"
+latest_android_hardware_audio_sounddose = "android.hardware.audio.sounddose-V2"
 
 // Modules that depend on android.hardware.audio.sounddose directly can include
 // the following cc_defaults to avoid explicitly managing dependency versions
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index a2f0260..1d96a0e 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -11,6 +11,7 @@
     name: "VtsHalAudioTargetTestDefaults",
     defaults: [
         "latest_android_hardware_audio_common_ndk_static",
+        "latest_android_hardware_audio_effect_ndk_static",
         "latest_android_media_audio_common_types_ndk_static",
         "use_libaidlvintf_gtest_helper_static",
         "VtsHalTargetTestDefaults",
@@ -20,7 +21,6 @@
         "libfmq",
     ],
     static_libs: [
-        "android.hardware.audio.effect-V1-ndk",
         "android.hardware.common-V2-ndk",
         "android.hardware.common.fmq-V1-ndk",
         "libaudioaidlcommon",
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/audiocontrol/aidl/Android.bp b/automotive/audiocontrol/aidl/Android.bp
index 9ae77cd..86b63a6 100644
--- a/automotive/audiocontrol/aidl/Android.bp
+++ b/automotive/audiocontrol/aidl/Android.bp
@@ -13,9 +13,9 @@
     name: "android.hardware.automotive.audiocontrol",
     vendor_available: true,
     srcs: ["android/hardware/automotive/audiocontrol/*.aidl"],
-    imports: [
-        "android.hardware.audio.common-V1",
-        "android.media.audio.common.types-V2",
+    defaults: [
+        "latest_android_hardware_audio_common_import_interface",
+        "latest_android_media_audio_common_types_import_interface",
     ],
     stability: "vintf",
     backend: {
@@ -52,6 +52,37 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
+
+// Note: This should always be one version ahead of the last frozen version
+latest_android_hardware_automotive_audiocontrol = "android.hardware.automotive.audiocontrol-V4"
+
+cc_defaults {
+    name: "latest_android_hardware_automotive_audiocontrol_cpp_static",
+    static_libs: [
+        latest_android_hardware_automotive_audiocontrol + "-cpp",
+    ],
+}
+
+cc_defaults {
+    name: "latest_android_hardware_automotive_audiocontrol_cpp_shared",
+    shared_libs: [
+        latest_android_hardware_automotive_audiocontrol + "-cpp",
+    ],
+}
+
+cc_defaults {
+    name: "latest_android_hardware_automotive_audiocontrol_ndk_static",
+    static_libs: [
+        latest_android_hardware_automotive_audiocontrol + "-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "latest_android_hardware_automotive_audiocontrol_ndk_shared",
+    shared_libs: [
+        latest_android_hardware_automotive_audiocontrol + "-ndk",
+    ],
+}
diff --git a/automotive/audiocontrol/aidl/default/audiocontrol-default.xml b/automotive/audiocontrol/aidl/default/audiocontrol-default.xml
index 95cd7f0..bcb5669 100644
--- a/automotive/audiocontrol/aidl/default/audiocontrol-default.xml
+++ b/automotive/audiocontrol/aidl/default/audiocontrol-default.xml
@@ -1,7 +1,7 @@
 <manifest version="2.0" type="device">
     <hal format="aidl">
         <name>android.hardware.automotive.audiocontrol</name>
-        <version>3</version>
+        <version>4</version>
         <fqname>IAudioControl/default</fqname>
     </hal>
 </manifest>
diff --git a/automotive/audiocontrol/aidl/vts/Android.bp b/automotive/audiocontrol/aidl/vts/Android.bp
index cfc2a3e..c73ad79 100644
--- a/automotive/audiocontrol/aidl/vts/Android.bp
+++ b/automotive/audiocontrol/aidl/vts/Android.bp
@@ -24,6 +24,8 @@
 cc_test {
     name: "VtsAidlHalAudioControlTest",
     defaults: [
+        "latest_android_hardware_audio_common_cpp_static",
+        "latest_android_hardware_automotive_audiocontrol_cpp_static",
         "latest_android_media_audio_common_types_cpp_static",
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
@@ -38,8 +40,6 @@
         "libxml2",
     ],
     static_libs: [
-        "android.hardware.automotive.audiocontrol-V3-cpp",
-        "android.hardware.audio.common-V1-cpp",
         "libgmock",
     ],
     test_suites: [
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/remoteaccess/hal/default/fuzzer/fuzzer.cpp b/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp
index 292c80e..9224ebc 100644
--- a/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp
+++ b/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp
@@ -55,6 +55,31 @@
         return Status::OK;
     }
 
+    Status ScheduleTask(ClientContext* context, const ScheduleTaskRequest& request,
+                        ScheduleTaskResponse* response) {
+        return Status::OK;
+    }
+
+    Status UnscheduleTask(ClientContext* context, const UnscheduleTaskRequest& request,
+                          UnscheduleTaskResponse* response) {
+        return Status::OK;
+    }
+
+    Status UnscheduleAllTasks(ClientContext* context, const UnscheduleAllTasksRequest& request,
+                              UnscheduleAllTasksResponse* response) {
+        return Status::OK;
+    }
+
+    Status IsTaskScheduled(ClientContext* context, const IsTaskScheduledRequest& request,
+                           IsTaskScheduledResponse* response) {
+        return Status::OK;
+    }
+
+    Status GetAllScheduledTasks(ClientContext* context, const GetAllScheduledTasksRequest& request,
+                                GetAllScheduledTasksResponse* response) {
+        return Status::OK;
+    }
+
     // Async methods which we do not care.
     ClientAsyncReaderInterface<GetRemoteTasksResponse>* AsyncGetRemoteTasksRaw(
             [[maybe_unused]] ClientContext* context,
@@ -83,6 +108,76 @@
                                         [[maybe_unused]] CompletionQueue* c) {
         return nullptr;
     }
+
+    ClientAsyncResponseReaderInterface<ScheduleTaskResponse>* AsyncScheduleTaskRaw(
+            [[maybe_unused]] ClientContext* context,
+            [[maybe_unused]] const ScheduleTaskRequest& request,
+            [[maybe_unused]] CompletionQueue* cq) {
+        return nullptr;
+    }
+
+    ClientAsyncResponseReaderInterface<ScheduleTaskResponse>* PrepareAsyncScheduleTaskRaw(
+            [[maybe_unused]] ClientContext* context,
+            [[maybe_unused]] const ScheduleTaskRequest& request,
+            [[maybe_unused]] CompletionQueue* c) {
+        return nullptr;
+    }
+
+    ClientAsyncResponseReaderInterface<UnscheduleTaskResponse>* AsyncUnscheduleTaskRaw(
+            [[maybe_unused]] ClientContext* context,
+            [[maybe_unused]] const UnscheduleTaskRequest& request,
+            [[maybe_unused]] CompletionQueue* cq) {
+        return nullptr;
+    }
+
+    ClientAsyncResponseReaderInterface<UnscheduleTaskResponse>* PrepareAsyncUnscheduleTaskRaw(
+            [[maybe_unused]] ClientContext* context,
+            [[maybe_unused]] const UnscheduleTaskRequest& request,
+            [[maybe_unused]] CompletionQueue* c) {
+        return nullptr;
+    }
+
+    ClientAsyncResponseReaderInterface<UnscheduleAllTasksResponse>* AsyncUnscheduleAllTasksRaw(
+            [[maybe_unused]] ClientContext* context,
+            [[maybe_unused]] const UnscheduleAllTasksRequest& request,
+            [[maybe_unused]] CompletionQueue* cq) {
+        return nullptr;
+    }
+
+    ClientAsyncResponseReaderInterface<UnscheduleAllTasksResponse>*
+    PrepareAsyncUnscheduleAllTasksRaw([[maybe_unused]] ClientContext* context,
+                                      [[maybe_unused]] const UnscheduleAllTasksRequest& request,
+                                      [[maybe_unused]] CompletionQueue* c) {
+        return nullptr;
+    }
+
+    ClientAsyncResponseReaderInterface<IsTaskScheduledResponse>* AsyncIsTaskScheduledRaw(
+            [[maybe_unused]] ClientContext* context,
+            [[maybe_unused]] const IsTaskScheduledRequest& request,
+            [[maybe_unused]] CompletionQueue* cq) {
+        return nullptr;
+    }
+
+    ClientAsyncResponseReaderInterface<IsTaskScheduledResponse>* PrepareAsyncIsTaskScheduledRaw(
+            [[maybe_unused]] ClientContext* context,
+            [[maybe_unused]] const IsTaskScheduledRequest& request,
+            [[maybe_unused]] CompletionQueue* c) {
+        return nullptr;
+    }
+
+    ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>* AsyncGetAllScheduledTasksRaw(
+            [[maybe_unused]] ClientContext* context,
+            [[maybe_unused]] const GetAllScheduledTasksRequest& request,
+            [[maybe_unused]] CompletionQueue* cq) {
+        return nullptr;
+    }
+
+    ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>*
+    PrepareAsyncGetAllScheduledTasksRaw([[maybe_unused]] ClientContext* context,
+                                        [[maybe_unused]] const GetAllScheduledTasksRequest& request,
+                                        [[maybe_unused]] CompletionQueue* c) {
+        return nullptr;
+    }
 };
 
 }  // namespace remoteaccess
diff --git a/automotive/remoteaccess/hal/default/proto/wakeup_client.proto b/automotive/remoteaccess/hal/default/proto/wakeup_client.proto
index 4fe0d01..e061016 100644
--- a/automotive/remoteaccess/hal/default/proto/wakeup_client.proto
+++ b/automotive/remoteaccess/hal/default/proto/wakeup_client.proto
@@ -18,6 +18,12 @@
 
 package android.hardware.automotive.remoteaccess;
 
+enum ErrorCode {
+    OK = 0;
+    UNSPECIFIED = 1;
+    INVALID_ARG = 2;
+}
+
 /**
  * Service provided by a wakeup client running on TCU.
  */
@@ -50,6 +56,50 @@
      * to wake up AP.
      */
     rpc NotifyWakeupRequired(NotifyWakeupRequiredRequest) returns (NotifyWakeupRequiredResponse) {}
+
+    /**
+     * Schedules a task to be executed later even when the vehicle is off.
+     *
+     * <p>This sends a scheduled task message to a device external to Android so that the device
+     * can wake up Android and deliver the task through {@link IRemoteTaskCallback}.
+     *
+     * <p>Note that the scheduled task execution is on a best-effort basis. Multiple situations
+     * might cause the task not to execute successfully:
+     *
+     * <ul>
+     * <li>The vehicle is low on battery and the other device decides not to wake up Android.
+     * <li>User turns off vehicle while the task is executing.
+     * <li>The task logic itself fails.
+     *
+     * <p>Must return a response with error code: {@code INVALID_ARG} if a pending schedule with the
+     * same {@code scheduleId} for this client exists.
+     */
+    rpc ScheduleTask(ScheduleTaskRequest) returns (ScheduleTaskResponse) {}
+
+    /**
+     * Unschedules a scheduled task.
+     *
+     * <p>Does nothing if a pending schedule with {@code clientId} and {@code scheduleId} does not
+     * exist.
+     */
+    rpc UnscheduleTask(UnscheduleTaskRequest) returns (UnscheduleTaskResponse) {}
+
+    /**
+     * Unschedules all scheduled tasks for the client.
+     */
+    rpc UnscheduleAllTasks(UnscheduleAllTasksRequest) returns (UnscheduleAllTasksResponse) {}
+
+    /**
+     * Returns whether the specified task is scheduled.
+     */
+    rpc IsTaskScheduled(IsTaskScheduledRequest) returns (IsTaskScheduledResponse) {}
+
+    /**
+     * Gets all pending scheduled tasks for the client.
+     *
+     * <p>The finished scheduled tasks will not be included.
+     */
+    rpc GetAllScheduledTasks(GetAllScheduledTasksRequest) returns (GetAllScheduledTasksResponse) {}
 }
 
 message GetRemoteTasksRequest {}
@@ -64,3 +114,50 @@
 }
 
 message NotifyWakeupRequiredResponse {}
+
+message ScheduleTaskRequest {
+    GrpcScheduleInfo scheduleInfo = 1;
+}
+
+message ScheduleTaskResponse {
+    ErrorCode errorCode = 1;
+}
+
+message GrpcScheduleInfo {
+    string clientId = 1;
+    string scheduleId = 2;
+    bytes data = 3;
+    int32 count = 4;
+    int64 startTimeInEpochSeconds = 5;
+    int64 periodicInSeconds = 6;
+}
+
+message UnscheduleTaskRequest {
+    string clientId = 1;
+    string scheduleId = 2;
+}
+
+message UnscheduleTaskResponse {}
+
+message UnscheduleAllTasksRequest {
+    string clientId = 1;
+}
+
+message UnscheduleAllTasksResponse {}
+
+message IsTaskScheduledRequest {
+    string clientId = 1;
+    string scheduleId = 2;
+}
+
+message IsTaskScheduledResponse {
+    bool isTaskScheduled = 1;
+}
+
+message GetAllScheduledTasksRequest {
+    string clientId = 1;
+}
+
+message GetAllScheduledTasksResponse {
+    repeated GrpcScheduleInfo allScheduledTasks = 1;
+}
diff --git a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
index 7721bf4..0944d86 100644
--- a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
+++ b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
@@ -314,38 +314,106 @@
     return ScopedAStatus::ok();
 }
 
-ScopedAStatus RemoteAccessService::isTaskScheduleSupported([[maybe_unused]] bool* out) {
-    // TODO(b/297271235): implement this.
+ScopedAStatus RemoteAccessService::isTaskScheduleSupported(bool* out) {
+    *out = true;
     return ScopedAStatus::ok();
 }
 
-ScopedAStatus RemoteAccessService::scheduleTask([[maybe_unused]] const ScheduleInfo& scheduleInfo) {
-    // TODO(b/297271235): implement this.
+ScopedAStatus RemoteAccessService::scheduleTask(const ScheduleInfo& scheduleInfo) {
+    ClientContext context;
+    ScheduleTaskRequest request = {};
+    ScheduleTaskResponse response = {};
+    request.mutable_scheduleinfo()->set_clientid(scheduleInfo.clientId);
+    request.mutable_scheduleinfo()->set_scheduleid(scheduleInfo.scheduleId);
+    request.mutable_scheduleinfo()->set_data(scheduleInfo.taskData.data(),
+                                             scheduleInfo.taskData.size());
+    request.mutable_scheduleinfo()->set_count(scheduleInfo.count);
+    request.mutable_scheduleinfo()->set_starttimeinepochseconds(
+            scheduleInfo.startTimeInEpochSeconds);
+    request.mutable_scheduleinfo()->set_periodicinseconds(scheduleInfo.periodicInSeconds);
+    Status status = mGrpcStub->ScheduleTask(&context, request, &response);
+    if (!status.ok()) {
+        return rpcStatusToScopedAStatus(status, "Failed to call ScheduleTask");
+    }
+    int errorCode = response.errorcode();
+    switch (errorCode) {
+        case ErrorCode::OK:
+            return ScopedAStatus::ok();
+        case ErrorCode::INVALID_ARG:
+            return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        default:
+            // Should not happen.
+            return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                    -1, ("Got unknown error code: " + ErrorCode_Name(errorCode) +
+                         " from remote access HAL")
+                                .c_str());
+    }
+}
+
+ScopedAStatus RemoteAccessService::unscheduleTask(const std::string& clientId,
+                                                  const std::string& scheduleId) {
+    ClientContext context;
+    UnscheduleTaskRequest request = {};
+    UnscheduleTaskResponse response = {};
+    request.set_clientid(clientId);
+    request.set_scheduleid(scheduleId);
+    Status status = mGrpcStub->UnscheduleTask(&context, request, &response);
+    if (!status.ok()) {
+        return rpcStatusToScopedAStatus(status, "Failed to call UnscheduleTask");
+    }
     return ScopedAStatus::ok();
 }
 
-ScopedAStatus RemoteAccessService::unscheduleTask([[maybe_unused]] const std::string& clientId,
-                                                  [[maybe_unused]] const std::string& scheduleId) {
-    // TODO(b/297271235): implement this.
+ScopedAStatus RemoteAccessService::unscheduleAllTasks(const std::string& clientId) {
+    ClientContext context;
+    UnscheduleAllTasksRequest request = {};
+    UnscheduleAllTasksResponse response = {};
+    request.set_clientid(clientId);
+    Status status = mGrpcStub->UnscheduleAllTasks(&context, request, &response);
+    if (!status.ok()) {
+        return rpcStatusToScopedAStatus(status, "Failed to call UnscheduleAllTasks");
+    }
     return ScopedAStatus::ok();
 }
 
-ScopedAStatus RemoteAccessService::unscheduleAllTasks(
-        [[maybe_unused]] const std::string& clientId) {
-    // TODO(b/297271235): implement this.
-    return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::isTaskScheduled([[maybe_unused]] const std::string& clientId,
-                                                   [[maybe_unused]] const std::string& scheduleId,
-                                                   [[maybe_unused]] bool* out) {
-    // TODO(b/297271235): implement this.
+ScopedAStatus RemoteAccessService::isTaskScheduled(const std::string& clientId,
+                                                   const std::string& scheduleId, bool* out) {
+    ClientContext context;
+    IsTaskScheduledRequest request = {};
+    IsTaskScheduledResponse response = {};
+    request.set_clientid(clientId);
+    request.set_scheduleid(scheduleId);
+    Status status = mGrpcStub->IsTaskScheduled(&context, request, &response);
+    if (!status.ok()) {
+        return rpcStatusToScopedAStatus(status, "Failed to call isTaskScheduled");
+    }
+    *out = response.istaskscheduled();
     return ScopedAStatus::ok();
 }
 
 ScopedAStatus RemoteAccessService::getAllScheduledTasks(const std::string& clientId,
                                                         std::vector<ScheduleInfo>* out) {
-    // TODO(b/297271235): implement this.
+    ClientContext context;
+    GetAllScheduledTasksRequest request = {};
+    GetAllScheduledTasksResponse response = {};
+    request.set_clientid(clientId);
+    Status status = mGrpcStub->GetAllScheduledTasks(&context, request, &response);
+    if (!status.ok()) {
+        return rpcStatusToScopedAStatus(status, "Failed to call isTaskScheduled");
+    }
+    out->clear();
+    for (int i = 0; i < response.allscheduledtasks_size(); i++) {
+        const GrpcScheduleInfo& rpcScheduleInfo = response.allscheduledtasks(i);
+        ScheduleInfo scheduleInfo = {
+                .clientId = rpcScheduleInfo.clientid(),
+                .scheduleId = rpcScheduleInfo.scheduleid(),
+                .taskData = stringToBytes(rpcScheduleInfo.data()),
+                .count = rpcScheduleInfo.count(),
+                .startTimeInEpochSeconds = rpcScheduleInfo.starttimeinepochseconds(),
+                .periodicInSeconds = rpcScheduleInfo.periodicinseconds(),
+        };
+        out->push_back(std::move(scheduleInfo));
+    }
     return ScopedAStatus::ok();
 }
 
diff --git a/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
index c5afd63..c0038c2 100644
--- a/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
+++ b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
@@ -21,6 +21,7 @@
 #include <aidl/android/hardware/automotive/remoteaccess/ApState.h>
 #include <aidl/android/hardware/automotive/remoteaccess/BnRemoteTaskCallback.h>
 #include <aidl/android/hardware/automotive/vehicle/VehiclePropValue.h>
+#include <android/binder_status.h>
 #include <gmock/gmock.h>
 #include <grpcpp/test/mock_stream.h>
 #include <gtest/gtest.h>
@@ -46,6 +47,7 @@
 
 using ::aidl::android::hardware::automotive::remoteaccess::ApState;
 using ::aidl::android::hardware::automotive::remoteaccess::BnRemoteTaskCallback;
+using ::aidl::android::hardware::automotive::remoteaccess::ScheduleInfo;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
 
 using ::grpc::ClientAsyncReaderInterface;
@@ -63,6 +65,12 @@
 using ::testing::SetArgPointee;
 
 constexpr char kTestVin[] = "test_VIN";
+const std::string kTestClientId = "test client id";
+const std::string kTestScheduleId = "test schedule id";
+const std::vector<uint8_t> kTestData = {0xde, 0xad, 0xbe, 0xef};
+constexpr int32_t kTestCount = 1234;
+constexpr int64_t kTestStartTimeInEpochSeconds = 2345;
+constexpr int64_t kTestPeriodicInSeconds = 123;
 
 }  // namespace
 
@@ -73,6 +81,21 @@
     MOCK_METHOD(Status, NotifyWakeupRequired,
                 (ClientContext * context, const NotifyWakeupRequiredRequest& request,
                  NotifyWakeupRequiredResponse* response));
+    MOCK_METHOD(Status, ScheduleTask,
+                (ClientContext * context, const ScheduleTaskRequest& request,
+                 ScheduleTaskResponse* response));
+    MOCK_METHOD(Status, UnscheduleTask,
+                (ClientContext * context, const UnscheduleTaskRequest& request,
+                 UnscheduleTaskResponse* response));
+    MOCK_METHOD(Status, UnscheduleAllTasks,
+                (ClientContext * context, const UnscheduleAllTasksRequest& request,
+                 UnscheduleAllTasksResponse* response));
+    MOCK_METHOD(Status, IsTaskScheduled,
+                (ClientContext * context, const IsTaskScheduledRequest& request,
+                 IsTaskScheduledResponse* response));
+    MOCK_METHOD(Status, GetAllScheduledTasks,
+                (ClientContext * context, const GetAllScheduledTasksRequest& request,
+                 GetAllScheduledTasksResponse* response));
     // Async methods which we do not care.
     MOCK_METHOD(ClientAsyncReaderInterface<GetRemoteTasksResponse>*, AsyncGetRemoteTasksRaw,
                 (ClientContext * context, const GetRemoteTasksRequest& request, CompletionQueue* cq,
@@ -88,6 +111,42 @@
                 PrepareAsyncNotifyWakeupRequiredRaw,
                 (ClientContext * context, const NotifyWakeupRequiredRequest& request,
                  CompletionQueue* cq));
+    MOCK_METHOD(ClientAsyncResponseReaderInterface<ScheduleTaskResponse>*, AsyncScheduleTaskRaw,
+                (ClientContext * context, const ScheduleTaskRequest& request, CompletionQueue* cq));
+    MOCK_METHOD(ClientAsyncResponseReaderInterface<ScheduleTaskResponse>*,
+                PrepareAsyncScheduleTaskRaw,
+                (ClientContext * context, const ScheduleTaskRequest& request, CompletionQueue* cq));
+    MOCK_METHOD(ClientAsyncResponseReaderInterface<UnscheduleTaskResponse>*, AsyncUnscheduleTaskRaw,
+                (ClientContext * context, const UnscheduleTaskRequest& request,
+                 CompletionQueue* cq));
+    MOCK_METHOD(ClientAsyncResponseReaderInterface<UnscheduleTaskResponse>*,
+                PrepareAsyncUnscheduleTaskRaw,
+                (ClientContext * context, const UnscheduleTaskRequest& request,
+                 CompletionQueue* cq));
+    MOCK_METHOD(ClientAsyncResponseReaderInterface<UnscheduleAllTasksResponse>*,
+                AsyncUnscheduleAllTasksRaw,
+                (ClientContext * context, const UnscheduleAllTasksRequest& request,
+                 CompletionQueue* cq));
+    MOCK_METHOD(ClientAsyncResponseReaderInterface<UnscheduleAllTasksResponse>*,
+                PrepareAsyncUnscheduleAllTasksRaw,
+                (ClientContext * context, const UnscheduleAllTasksRequest& request,
+                 CompletionQueue* cq));
+    MOCK_METHOD(ClientAsyncResponseReaderInterface<IsTaskScheduledResponse>*,
+                AsyncIsTaskScheduledRaw,
+                (ClientContext * context, const IsTaskScheduledRequest& request,
+                 CompletionQueue* cq));
+    MOCK_METHOD(ClientAsyncResponseReaderInterface<IsTaskScheduledResponse>*,
+                PrepareAsyncIsTaskScheduledRaw,
+                (ClientContext * context, const IsTaskScheduledRequest& request,
+                 CompletionQueue* cq));
+    MOCK_METHOD(ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>*,
+                AsyncGetAllScheduledTasksRaw,
+                (ClientContext * context, const GetAllScheduledTasksRequest& request,
+                 CompletionQueue* cq));
+    MOCK_METHOD(ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>*,
+                PrepareAsyncGetAllScheduledTasksRaw,
+                (ClientContext * context, const GetAllScheduledTasksRequest& request,
+                 CompletionQueue* cq));
 };
 
 class FakeVhalClient final : public android::frameworks::automotive::vhal::IVhalClient {
@@ -367,6 +426,174 @@
     ASSERT_EQ(vehicleId, kTestVin);
 }
 
+TEST_F(RemoteAccessServiceUnitTest, TestIsTaskScheduleSupported) {
+    bool out = false;
+    ScopedAStatus status = getService()->isTaskScheduleSupported(&out);
+
+    EXPECT_TRUE(status.isOk());
+    EXPECT_TRUE(out);
+}
+
+TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask) {
+    ScheduleTaskRequest grpcRequest = {};
+    EXPECT_CALL(*getGrpcWakeupClientStub(), ScheduleTask)
+            .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context,
+                                     const ScheduleTaskRequest& request,
+                                     [[maybe_unused]] ScheduleTaskResponse* response) {
+                grpcRequest = request;
+                return Status();
+            });
+    ScheduleInfo scheduleInfo = {
+            .clientId = kTestClientId,
+            .scheduleId = kTestScheduleId,
+            .taskData = kTestData,
+            .count = kTestCount,
+            .startTimeInEpochSeconds = kTestStartTimeInEpochSeconds,
+            .periodicInSeconds = kTestPeriodicInSeconds,
+    };
+
+    ScopedAStatus status = getService()->scheduleTask(scheduleInfo);
+
+    ASSERT_TRUE(status.isOk());
+    EXPECT_EQ(grpcRequest.scheduleinfo().clientid(), kTestClientId);
+    EXPECT_EQ(grpcRequest.scheduleinfo().scheduleid(), kTestScheduleId);
+    EXPECT_EQ(grpcRequest.scheduleinfo().data(), std::string(kTestData.begin(), kTestData.end()));
+    EXPECT_EQ(grpcRequest.scheduleinfo().count(), kTestCount);
+    EXPECT_EQ(grpcRequest.scheduleinfo().starttimeinepochseconds(), kTestStartTimeInEpochSeconds);
+    EXPECT_EQ(grpcRequest.scheduleinfo().periodicinseconds(), kTestPeriodicInSeconds);
+}
+
+TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask_InvalidArg) {
+    EXPECT_CALL(*getGrpcWakeupClientStub(), ScheduleTask)
+            .WillOnce([]([[maybe_unused]] ClientContext* context,
+                         [[maybe_unused]] const ScheduleTaskRequest& request,
+                         ScheduleTaskResponse* response) {
+                response->set_errorcode(ErrorCode::INVALID_ARG);
+                return Status();
+            });
+    ScheduleInfo scheduleInfo = {
+            .clientId = kTestClientId,
+            .scheduleId = kTestScheduleId,
+            .taskData = kTestData,
+            .count = kTestCount,
+            .startTimeInEpochSeconds = kTestStartTimeInEpochSeconds,
+            .periodicInSeconds = kTestPeriodicInSeconds,
+    };
+
+    ScopedAStatus status = getService()->scheduleTask(scheduleInfo);
+
+    ASSERT_FALSE(status.isOk());
+    ASSERT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+}
+
+TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask_UnspecifiedError) {
+    EXPECT_CALL(*getGrpcWakeupClientStub(), ScheduleTask)
+            .WillOnce([]([[maybe_unused]] ClientContext* context,
+                         [[maybe_unused]] const ScheduleTaskRequest& request,
+                         ScheduleTaskResponse* response) {
+                response->set_errorcode(ErrorCode::UNSPECIFIED);
+                return Status();
+            });
+    ScheduleInfo scheduleInfo = {
+            .clientId = kTestClientId,
+            .scheduleId = kTestScheduleId,
+            .taskData = kTestData,
+            .count = kTestCount,
+            .startTimeInEpochSeconds = kTestStartTimeInEpochSeconds,
+            .periodicInSeconds = kTestPeriodicInSeconds,
+    };
+
+    ScopedAStatus status = getService()->scheduleTask(scheduleInfo);
+
+    ASSERT_FALSE(status.isOk());
+    ASSERT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC);
+}
+
+TEST_F(RemoteAccessServiceUnitTest, TestUnscheduleTask) {
+    UnscheduleTaskRequest grpcRequest = {};
+    EXPECT_CALL(*getGrpcWakeupClientStub(), UnscheduleTask)
+            .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context,
+                                     const UnscheduleTaskRequest& request,
+                                     [[maybe_unused]] UnscheduleTaskResponse* response) {
+                grpcRequest = request;
+                return Status();
+            });
+
+    ScopedAStatus status = getService()->unscheduleTask(kTestClientId, kTestScheduleId);
+
+    ASSERT_TRUE(status.isOk());
+    EXPECT_EQ(grpcRequest.clientid(), kTestClientId);
+    EXPECT_EQ(grpcRequest.scheduleid(), kTestScheduleId);
+}
+
+TEST_F(RemoteAccessServiceUnitTest, TestUnscheduleAllTasks) {
+    UnscheduleAllTasksRequest grpcRequest = {};
+    EXPECT_CALL(*getGrpcWakeupClientStub(), UnscheduleAllTasks)
+            .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context,
+                                     const UnscheduleAllTasksRequest& request,
+                                     [[maybe_unused]] UnscheduleAllTasksResponse* response) {
+                grpcRequest = request;
+                return Status();
+            });
+
+    ScopedAStatus status = getService()->unscheduleAllTasks(kTestClientId);
+
+    ASSERT_TRUE(status.isOk());
+    EXPECT_EQ(grpcRequest.clientid(), kTestClientId);
+}
+
+TEST_F(RemoteAccessServiceUnitTest, TestIsTaskScheduled) {
+    bool isTaskScheduled = false;
+    IsTaskScheduledRequest grpcRequest = {};
+    EXPECT_CALL(*getGrpcWakeupClientStub(), IsTaskScheduled)
+            .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context,
+                                     const IsTaskScheduledRequest& request,
+                                     IsTaskScheduledResponse* response) {
+                grpcRequest = request;
+                response->set_istaskscheduled(true);
+                return Status();
+            });
+
+    ScopedAStatus status =
+            getService()->isTaskScheduled(kTestClientId, kTestScheduleId, &isTaskScheduled);
+
+    ASSERT_TRUE(status.isOk());
+    EXPECT_TRUE(isTaskScheduled);
+    EXPECT_EQ(grpcRequest.clientid(), kTestClientId);
+    EXPECT_EQ(grpcRequest.scheduleid(), kTestScheduleId);
+}
+
+TEST_F(RemoteAccessServiceUnitTest, testGetAllScheduledTasks) {
+    std::vector<ScheduleInfo> result;
+    GetAllScheduledTasksRequest grpcRequest = {};
+    EXPECT_CALL(*getGrpcWakeupClientStub(), GetAllScheduledTasks)
+            .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context,
+                                     const GetAllScheduledTasksRequest& request,
+                                     GetAllScheduledTasksResponse* response) {
+                grpcRequest = request;
+                GrpcScheduleInfo* newInfo = response->add_allscheduledtasks();
+                newInfo->set_clientid(kTestClientId);
+                newInfo->set_scheduleid(kTestScheduleId);
+                newInfo->set_data(kTestData.data(), kTestData.size());
+                newInfo->set_count(kTestCount);
+                newInfo->set_starttimeinepochseconds(kTestStartTimeInEpochSeconds);
+                newInfo->set_periodicinseconds(kTestPeriodicInSeconds);
+                return Status();
+            });
+
+    ScopedAStatus status = getService()->getAllScheduledTasks(kTestClientId, &result);
+
+    ASSERT_TRUE(status.isOk());
+    EXPECT_EQ(grpcRequest.clientid(), kTestClientId);
+    ASSERT_EQ(result.size(), 1u);
+    ASSERT_EQ(result[0].clientId, kTestClientId);
+    ASSERT_EQ(result[0].scheduleId, kTestScheduleId);
+    ASSERT_EQ(result[0].taskData, kTestData);
+    ASSERT_EQ(result[0].count, kTestCount);
+    ASSERT_EQ(result[0].startTimeInEpochSeconds, kTestStartTimeInEpochSeconds);
+    ASSERT_EQ(result[0].periodicInSeconds, kTestPeriodicInSeconds);
+}
+
 }  // namespace remoteaccess
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/remoteaccess/test_grpc_server/impl/Android.bp b/automotive/remoteaccess/test_grpc_server/impl/Android.bp
index 74c810e..fd174bf 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/Android.bp
+++ b/automotive/remoteaccess/test_grpc_server/impl/Android.bp
@@ -61,3 +61,27 @@
         "-DHOST",
     ],
 }
+
+cc_test_host {
+    name: "TestWakeupClientServerHostUnitTest",
+    srcs: [
+        "test/*.cpp",
+        "src/TestWakeupClientServiceImpl.cpp",
+    ],
+    local_include_dirs: ["include"],
+    shared_libs: [
+        "libbase",
+        "libutils",
+        "libgrpc++",
+        "libprotobuf-cpp-full",
+    ],
+    static_libs: [
+        "libgtest",
+    ],
+    whole_static_libs: [
+        "wakeup_client_protos",
+    ],
+    cflags: [
+        "-Wno-unused-parameter",
+    ],
+}
diff --git a/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
index 4159e83..2aab904 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
+++ b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
@@ -71,30 +71,41 @@
 // TaskQueue is thread-safe.
 class TaskQueue final {
   public:
-    TaskQueue();
-    ~TaskQueue();
+    TaskQueue(android::sp<Looper> looper);
 
     void add(const GetRemoteTasksResponse& response);
     std::optional<GetRemoteTasksResponse> maybePopOne();
     void waitForTask();
     void stopWait();
-    void handleTaskTimeout();
     bool isEmpty();
 
   private:
-    std::thread mCheckTaskTimeoutThread;
+    friend class TaskTimeoutMessageHandler;
+
     std::mutex mLock;
     std::priority_queue<TaskInfo, std::vector<TaskInfo>, TaskInfoComparator> mTasks
             GUARDED_BY(mLock);
     // A variable to notify mTasks is not empty.
     std::condition_variable mTasksNotEmptyCv;
-    bool mStopped GUARDED_BY(mLock);
+    std::atomic<bool> mStopped;
     android::sp<Looper> mLooper;
     android::sp<TaskTimeoutMessageHandler> mTaskTimeoutMessageHandler;
     std::atomic<int> mTaskIdCounter = 0;
 
-    void checkForTestTimeoutLoop();
-    void waitForTaskWithLock(std::unique_lock<std::mutex>& lock);
+    void loop();
+    void handleTaskTimeout();
+};
+
+// forward-declaration
+class TestWakeupClientServiceImpl;
+
+class TaskScheduleMsgHandler final : public android::MessageHandler {
+  public:
+    TaskScheduleMsgHandler(TestWakeupClientServiceImpl* mImpl);
+    void handleMessage(const android::Message& message) override;
+
+  private:
+    TestWakeupClientServiceImpl* mImpl;
 };
 
 class TestWakeupClientServiceImpl : public WakeupClient::Service {
@@ -103,6 +114,9 @@
 
     ~TestWakeupClientServiceImpl();
 
+    // Stop the handling for all income requests. Prepare for shutdown.
+    void stopServer();
+
     grpc::Status GetRemoteTasks(grpc::ServerContext* context, const GetRemoteTasksRequest* request,
                                 grpc::ServerWriter<GetRemoteTasksResponse>* writer) override;
 
@@ -110,6 +124,24 @@
                                       const NotifyWakeupRequiredRequest* request,
                                       NotifyWakeupRequiredResponse* response) override;
 
+    grpc::Status ScheduleTask(grpc::ServerContext* context, const ScheduleTaskRequest* request,
+                              ScheduleTaskResponse* response) override;
+
+    grpc::Status UnscheduleTask(grpc::ServerContext* context, const UnscheduleTaskRequest* request,
+                                UnscheduleTaskResponse* response) override;
+
+    grpc::Status UnscheduleAllTasks(grpc::ServerContext* context,
+                                    const UnscheduleAllTasksRequest* request,
+                                    UnscheduleAllTasksResponse* response) override;
+
+    grpc::Status IsTaskScheduled(grpc::ServerContext* context,
+                                 const IsTaskScheduledRequest* request,
+                                 IsTaskScheduledResponse* response) override;
+
+    grpc::Status GetAllScheduledTasks(grpc::ServerContext* context,
+                                      const GetAllScheduledTasksRequest* request,
+                                      GetAllScheduledTasksResponse* response) override;
+
     /**
      * Starts generating fake tasks for the specific client repeatedly.
      *
@@ -117,22 +149,27 @@
      * to the client every 5s.
      */
     void startGeneratingFakeTask(const std::string& clientId);
+
     /**
      * stops generating fake tasks.
      */
     void stopGeneratingFakeTask();
+
     /**
      * Returns whether we need to wakeup the target device to send remote tasks.
      */
     bool isWakeupRequired();
+
     /**
      * Returns whether we have an active connection with the target device.
      */
     bool isRemoteTaskConnectionAlive();
+
     /**
      * Injects a fake task with taskData to be sent to the specific client.
      */
     void injectTask(const std::string& taskData, const std::string& clientId);
+
     /**
      * Wakes up the target device.
      *
@@ -141,10 +178,34 @@
      */
     virtual void wakeupApplicationProcessor() = 0;
 
+    /**
+     * Cleans up a scheduled task info.
+     */
+    void cleanupScheduledTaskLocked(const std::string& clientId, const std::string& scheduleId)
+            REQUIRES(mLock);
+
   private:
-    // This is a thread for communicating with remote wakeup server (via network) and receive tasks
-    // from it.
-    std::thread mThread;
+    friend class TaskScheduleMsgHandler;
+
+    struct ScheduleInfo {
+        std::unique_ptr<GrpcScheduleInfo> grpcScheduleInfo;
+        // This is a unique ID to represent this schedule. Each repeated tasks will have different
+        // task ID but will have the same scheduleMsgId so that we can use to unschedule. This has
+        // to be an int so we cannot use the scheduleId provided by the client.
+        int scheduleMsgId;
+        int64_t periodicInSeconds;
+        int32_t currentCount;
+        int32_t totalCount;
+    };
+
+    std::atomic<int> mScheduleMsgCounter = 0;
+    // This is a looper for scheduling tasks to be executed in the future.
+    android::sp<Looper> mLooper;
+    android::sp<TaskScheduleMsgHandler> mTaskScheduleMsgHandler;
+    // This is a thread for generating fake tasks.
+    std::thread mFakeTaskThread;
+    // This is a thread for the looper.
+    std::thread mLooperThread;
     // A variable to notify server is stopping.
     std::condition_variable mTaskLoopStoppedCv;
     // Whether wakeup AP is required for executing tasks.
@@ -153,14 +214,21 @@
     std::atomic<bool> mRemoteTaskConnectionAlive = false;
     std::mutex mLock;
     bool mGeneratingFakeTask GUARDED_BY(mLock);
+    std::atomic<bool> mServerStopped;
+    std::unordered_map<std::string, std::unordered_map<std::string, ScheduleInfo>>
+            mInfoByScheduleIdByClientId GUARDED_BY(mLock);
 
     // Thread-safe. For test impl only.
     FakeTaskGenerator mFakeTaskGenerator;
-    // Thread-sfae.
-    TaskQueue mTaskQueue;
+    // Thread-safe.
+    std::unique_ptr<TaskQueue> mTaskQueue;
 
     void fakeTaskGenerateLoop(const std::string& clientId);
     void injectTaskResponse(const GetRemoteTasksResponse& response);
+    bool getScheduleInfoLocked(int scheduleMsgId, ScheduleInfo** outScheduleInfoPtr)
+            REQUIRES(mLock);
+    void handleAddTask(int scheduleMsgId);
+    void loop();
 };
 
 }  // namespace remoteaccess
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
index eb3871b..1db991c 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
@@ -37,8 +37,17 @@
 using ::grpc::ServerWriter;
 using ::grpc::Status;
 
-constexpr int kTaskIntervalInMs = 5'000;
-constexpr int64_t KTaskTimeoutInMs = 20'000;
+constexpr int64_t kTaskIntervalInMs = 5'000;
+constexpr int64_t kTaskTimeoutInMs = 20'000;
+
+int64_t msToNs(int64_t ms) {
+    return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::milliseconds(ms))
+            .count();
+}
+
+int64_t sToNs(int64_t s) {
+    return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(s)).count();
+}
 
 }  // namespace
 
@@ -56,26 +65,9 @@
     mTaskQueue->handleTaskTimeout();
 }
 
-TaskQueue::TaskQueue() {
+TaskQueue::TaskQueue(android::sp<Looper> looper) {
     mTaskTimeoutMessageHandler = android::sp<TaskTimeoutMessageHandler>::make(this);
-    mLooper = Looper::prepare(/*opts=*/0);
-    mCheckTaskTimeoutThread = std::thread([this] { checkForTestTimeoutLoop(); });
-}
-
-TaskQueue::~TaskQueue() {
-    {
-        std::lock_guard<std::mutex> lockGuard(mLock);
-        mStopped = true;
-    }
-    while (true) {
-        // Remove all pending timeout handlers from queue.
-        if (!maybePopOne().has_value()) {
-            break;
-        }
-    }
-    if (mCheckTaskTimeoutThread.joinable()) {
-        mCheckTaskTimeoutThread.join();
-    }
+    mLooper = looper;
 }
 
 std::optional<GetRemoteTasksResponse> TaskQueue::maybePopOne() {
@@ -101,16 +93,12 @@
             .taskData = task,
     });
     android::Message message(taskId);
-    mLooper->sendMessageDelayed(KTaskTimeoutInMs * 1000, mTaskTimeoutMessageHandler, message);
+    mLooper->sendMessageDelayed(msToNs(kTaskTimeoutInMs), mTaskTimeoutMessageHandler, message);
     mTasksNotEmptyCv.notify_all();
 }
 
 void TaskQueue::waitForTask() {
     std::unique_lock<std::mutex> lock(mLock);
-    waitForTaskWithLock(lock);
-}
-
-void TaskQueue::waitForTaskWithLock(std::unique_lock<std::mutex>& lock) {
     mTasksNotEmptyCv.wait(lock, [this] {
         ScopedLockAssertion lockAssertion(mLock);
         return mTasks.size() > 0 || mStopped;
@@ -118,9 +106,11 @@
 }
 
 void TaskQueue::stopWait() {
-    std::lock_guard<std::mutex> lockGuard(mLock);
     mStopped = true;
-    mTasksNotEmptyCv.notify_all();
+    {
+        std::lock_guard<std::mutex> lockGuard(mLock);
+        mTasksNotEmptyCv.notify_all();
+    }
 }
 
 bool TaskQueue::isEmpty() {
@@ -128,21 +118,6 @@
     return mTasks.size() == 0 || mStopped;
 }
 
-void TaskQueue::checkForTestTimeoutLoop() {
-    Looper::setForThread(mLooper);
-
-    while (true) {
-        {
-            std::unique_lock<std::mutex> lock(mLock);
-            if (mStopped) {
-                return;
-            }
-        }
-
-        mLooper->pollAll(/*timeoutMillis=*/-1);
-    }
-}
-
 void TaskQueue::handleTaskTimeout() {
     // We know which task timed-out from the taskId in the message. However, there is no easy way
     // to remove a specific task with the task ID from the priority_queue, so we just check from
@@ -151,22 +126,50 @@
     int64_t now = uptimeMillis();
     while (mTasks.size() > 0) {
         const TaskInfo& taskInfo = mTasks.top();
-        if (taskInfo.timestampInMs + KTaskTimeoutInMs > now) {
+        if (taskInfo.timestampInMs + kTaskTimeoutInMs > now) {
             break;
         }
         // In real implementation, this should report task failure to remote wakeup server.
-        printf("Task for client ID: %s timed-out, added at %" PRId64 " ms, now %" PRId64 " ms",
+        printf("Task for client ID: %s timed-out, added at %" PRId64 " ms, now %" PRId64 " ms\n",
                taskInfo.taskData.clientid().c_str(), taskInfo.timestampInMs, now);
         mTasks.pop();
     }
 }
 
-TestWakeupClientServiceImpl::TestWakeupClientServiceImpl() {}
+TestWakeupClientServiceImpl::TestWakeupClientServiceImpl() {
+    mTaskScheduleMsgHandler = android::sp<TaskScheduleMsgHandler>::make(this);
+    mLooper = android::sp<Looper>::make(/*opts=*/0);
+    mLooperThread = std::thread([this] { loop(); });
+    mTaskQueue = std::make_unique<TaskQueue>(mLooper);
+}
 
 TestWakeupClientServiceImpl::~TestWakeupClientServiceImpl() {
-    { std::lock_guard<std::mutex> lockGuard(mLock); }
-    mTaskQueue.stopWait();
+    if (mServerStopped) {
+        return;
+    }
+    stopServer();
+}
+
+void TestWakeupClientServiceImpl::stopServer() {
+    mTaskQueue->stopWait();
     stopGeneratingFakeTask();
+    // Set the flag so that the loop thread will exit.
+    mServerStopped = true;
+    mLooper->wake();
+    if (mLooperThread.joinable()) {
+        mLooperThread.join();
+    }
+}
+
+void TestWakeupClientServiceImpl::loop() {
+    Looper::setForThread(mLooper);
+
+    while (true) {
+        mLooper->pollAll(/*timeoutMillis=*/-1);
+        if (mServerStopped) {
+            return;
+        }
+    }
 }
 
 void TestWakeupClientServiceImpl::injectTask(const std::string& taskData,
@@ -178,8 +181,8 @@
 }
 
 void TestWakeupClientServiceImpl::injectTaskResponse(const GetRemoteTasksResponse& response) {
-    printf("Received a new task\n");
-    mTaskQueue.add(response);
+    printf("Receive a new task\n");
+    mTaskQueue->add(response);
     if (mWakeupRequired) {
         wakeupApplicationProcessor();
     }
@@ -192,7 +195,7 @@
         return;
     }
     mGeneratingFakeTask = true;
-    mThread = std::thread([this, clientId] { fakeTaskGenerateLoop(clientId); });
+    mFakeTaskThread = std::thread([this, clientId] { fakeTaskGenerateLoop(clientId); });
     printf("Started generating fake tasks\n");
 }
 
@@ -206,8 +209,8 @@
         mTaskLoopStoppedCv.notify_all();
         mGeneratingFakeTask = false;
     }
-    if (mThread.joinable()) {
-        mThread.join();
+    if (mFakeTaskThread.joinable()) {
+        mFakeTaskThread.join();
     }
     printf("Stopped generating fake tasks\n");
 }
@@ -217,7 +220,7 @@
     // from it. Here we simulate receiving one remote task every {kTaskIntervalInMs}ms.
     while (true) {
         injectTaskResponse(mFakeTaskGenerator.generateTask(clientId));
-        printf("Sleeping for %d seconds until next task\n", kTaskIntervalInMs);
+        printf("Sleeping for %" PRId64 " seconds until next task\n", kTaskIntervalInMs);
 
         std::unique_lock lk(mLock);
         if (mTaskLoopStoppedCv.wait_for(lk, std::chrono::milliseconds(kTaskIntervalInMs), [this] {
@@ -236,10 +239,16 @@
     printf("GetRemoteTasks called\n");
     mRemoteTaskConnectionAlive = true;
     while (true) {
-        mTaskQueue.waitForTask();
+        mTaskQueue->waitForTask();
+
+        if (mServerStopped) {
+            // Server stopped, exit the loop.
+            printf("Server stopped exit loop\n");
+            break;
+        }
 
         while (true) {
-            auto maybeTask = mTaskQueue.maybePopOne();
+            auto maybeTask = mTaskQueue->maybePopOne();
             if (!maybeTask.has_value()) {
                 // No task left, loop again and wait for another task(s).
                 break;
@@ -252,21 +261,21 @@
                 printf("Failed to deliver remote task to remote access HAL\n");
                 // The task failed to be sent, add it back to the queue. The order might change, but
                 // it is okay.
-                mTaskQueue.add(response);
+                mTaskQueue->add(response);
                 mRemoteTaskConnectionAlive = false;
                 return Status::CANCELLED;
             }
         }
     }
-    mRemoteTaskConnectionAlive = false;
-    return Status::OK;
+    // Server stopped, exit the loop.
+    return Status::CANCELLED;
 }
 
 Status TestWakeupClientServiceImpl::NotifyWakeupRequired(ServerContext* context,
                                                          const NotifyWakeupRequiredRequest* request,
                                                          NotifyWakeupRequiredResponse* response) {
     printf("NotifyWakeupRequired called\n");
-    if (request->iswakeuprequired() && !mWakeupRequired && !mTaskQueue.isEmpty()) {
+    if (request->iswakeuprequired() && !mWakeupRequired && !mTaskQueue->isEmpty()) {
         // If wakeup is now required and previously not required, this means we have finished
         // shutting down the device. If there are still pending tasks, try waking up AP again
         // to finish executing those tasks.
@@ -281,6 +290,203 @@
     return Status::OK;
 }
 
+void TestWakeupClientServiceImpl::cleanupScheduledTaskLocked(const std::string& clientId,
+                                                             const std::string& scheduleId) {
+    mInfoByScheduleIdByClientId[clientId].erase(scheduleId);
+    if (mInfoByScheduleIdByClientId[clientId].size() == 0) {
+        mInfoByScheduleIdByClientId.erase(clientId);
+    }
+}
+
+TaskScheduleMsgHandler::TaskScheduleMsgHandler(TestWakeupClientServiceImpl* impl) : mImpl(impl) {}
+
+void TaskScheduleMsgHandler::handleMessage(const android::Message& message) {
+    mImpl->handleAddTask(message.what);
+}
+
+Status TestWakeupClientServiceImpl::ScheduleTask(ServerContext* context,
+                                                 const ScheduleTaskRequest* request,
+                                                 ScheduleTaskResponse* response) {
+    std::lock_guard<std::mutex> lockGuard(mLock);
+
+    const GrpcScheduleInfo& grpcScheduleInfo = request->scheduleinfo();
+    const std::string& scheduleId = grpcScheduleInfo.scheduleid();
+    const std::string& clientId = grpcScheduleInfo.clientid();
+    response->set_errorcode(ErrorCode::OK);
+
+    if (mInfoByScheduleIdByClientId.find(clientId) != mInfoByScheduleIdByClientId.end() &&
+        mInfoByScheduleIdByClientId[clientId].find(scheduleId) !=
+                mInfoByScheduleIdByClientId[clientId].end()) {
+        printf("Duplicate schedule Id: %s for client Id: %s\n", scheduleId.c_str(),
+               clientId.c_str());
+        response->set_errorcode(ErrorCode::INVALID_ARG);
+        return Status::OK;
+    }
+
+    int64_t startTimeInEpochSeconds = grpcScheduleInfo.starttimeinepochseconds();
+    int64_t periodicInSeconds = grpcScheduleInfo.periodicinseconds();
+    int32_t count = grpcScheduleInfo.count();
+
+    int scheduleMsgId = mScheduleMsgCounter++;
+    mInfoByScheduleIdByClientId[clientId][scheduleId] = {
+            .grpcScheduleInfo = std::make_unique<GrpcScheduleInfo>(grpcScheduleInfo),
+            .scheduleMsgId = scheduleMsgId,
+            .periodicInSeconds = periodicInSeconds,
+            .currentCount = 0,
+            .totalCount = count,
+    };
+
+    int64_t delayInSeconds =
+            startTimeInEpochSeconds - std::chrono::duration_cast<std::chrono::seconds>(
+                                              std::chrono::system_clock::now().time_since_epoch())
+                                              .count();
+    if (delayInSeconds < 0) {
+        delayInSeconds = 0;
+    }
+
+    printf("ScheduleTask called with client Id: %s, schedule Id: %s, delay: %" PRId64 " s\n",
+           clientId.c_str(), scheduleId.c_str(), delayInSeconds);
+
+    mLooper->sendMessageDelayed(sToNs(delayInSeconds), mTaskScheduleMsgHandler,
+                                android::Message(scheduleMsgId));
+
+    return Status::OK;
+}
+
+bool TestWakeupClientServiceImpl::getScheduleInfoLocked(int scheduleMsgId,
+                                                        ScheduleInfo** outScheduleInfoPtr) {
+    for (auto& [_, infoByScheduleId] : mInfoByScheduleIdByClientId) {
+        for (auto& [_, scheduleInfo] : infoByScheduleId) {
+            if (scheduleInfo.scheduleMsgId == scheduleMsgId) {
+                *outScheduleInfoPtr = &scheduleInfo;
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+void TestWakeupClientServiceImpl::handleAddTask(int scheduleMsgId) {
+    std::lock_guard<std::mutex> lockGuard(mLock);
+
+    ScheduleInfo* scheduleInfoPtr;
+    bool found = getScheduleInfoLocked(scheduleMsgId, &scheduleInfoPtr);
+    if (!found) {
+        printf("The schedule msg Id: %d is not found\n", scheduleMsgId);
+        return;
+    }
+
+    const GrpcScheduleInfo& grpcScheduleInfo = *scheduleInfoPtr->grpcScheduleInfo;
+    const std::string scheduleId = grpcScheduleInfo.scheduleid();
+    const std::string clientId = grpcScheduleInfo.clientid();
+
+    GetRemoteTasksResponse injectResponse;
+    injectResponse.set_data(grpcScheduleInfo.data().data(), grpcScheduleInfo.data().size());
+    injectResponse.set_clientid(clientId);
+    injectTaskResponse(injectResponse);
+    scheduleInfoPtr->currentCount++;
+
+    printf("Sending scheduled tasks for scheduleId: %s, clientId: %s, taskCount: %d\n",
+           scheduleId.c_str(), clientId.c_str(), scheduleInfoPtr->currentCount);
+
+    if (scheduleInfoPtr->totalCount != 0 &&
+        scheduleInfoPtr->currentCount == scheduleInfoPtr->totalCount) {
+        // This schedule is finished.
+        cleanupScheduledTaskLocked(clientId, scheduleId);
+        return;
+    }
+
+    // Schedule the task for the next period.
+    mLooper->sendMessageDelayed(sToNs(scheduleInfoPtr->periodicInSeconds), mTaskScheduleMsgHandler,
+                                android::Message(scheduleMsgId));
+}
+
+Status TestWakeupClientServiceImpl::UnscheduleTask(ServerContext* context,
+                                                   const UnscheduleTaskRequest* request,
+                                                   UnscheduleTaskResponse* response) {
+    std::lock_guard<std::mutex> lockGuard(mLock);
+
+    const std::string& clientId = request->clientid();
+    const std::string& scheduleId = request->scheduleid();
+    printf("UnscheduleTask called with client Id: %s, schedule Id: %s\n", clientId.c_str(),
+           scheduleId.c_str());
+
+    if (mInfoByScheduleIdByClientId.find(clientId) == mInfoByScheduleIdByClientId.end() ||
+        mInfoByScheduleIdByClientId[clientId].find(scheduleId) ==
+                mInfoByScheduleIdByClientId[clientId].end()) {
+        printf("UnscheduleTask: no task associated with clientId: %s, scheduleId: %s\n",
+               clientId.c_str(), scheduleId.c_str());
+        return Status::OK;
+    }
+
+    mLooper->removeMessages(mTaskScheduleMsgHandler,
+                            mInfoByScheduleIdByClientId[clientId][scheduleId].scheduleMsgId);
+    cleanupScheduledTaskLocked(clientId, scheduleId);
+    return Status::OK;
+}
+
+Status TestWakeupClientServiceImpl::UnscheduleAllTasks(ServerContext* context,
+                                                       const UnscheduleAllTasksRequest* request,
+                                                       UnscheduleAllTasksResponse* response) {
+    std::lock_guard<std::mutex> lockGuard(mLock);
+
+    const std::string& clientId = request->clientid();
+    printf("UnscheduleAllTasks called with client Id: %s\n", clientId.c_str());
+    if (mInfoByScheduleIdByClientId.find(clientId) == mInfoByScheduleIdByClientId.end()) {
+        printf("UnscheduleTask: no task associated with clientId: %s\n", clientId.c_str());
+        return Status::OK;
+    }
+    const auto& infoByScheduleId = mInfoByScheduleIdByClientId[clientId];
+    std::vector<int> scheduleMsgIds;
+    for (const auto& [_, scheduleInfo] : infoByScheduleId) {
+        mLooper->removeMessages(mTaskScheduleMsgHandler, /*what=*/scheduleInfo.scheduleMsgId);
+    }
+
+    mInfoByScheduleIdByClientId.erase(clientId);
+    return Status::OK;
+}
+
+Status TestWakeupClientServiceImpl::IsTaskScheduled(ServerContext* context,
+                                                    const IsTaskScheduledRequest* request,
+                                                    IsTaskScheduledResponse* response) {
+    std::lock_guard<std::mutex> lockGuard(mLock);
+
+    const std::string& clientId = request->clientid();
+    const std::string& scheduleId = request->scheduleid();
+    printf("IsTaskScheduled called with client Id: %s, scheduleId: %s\n", clientId.c_str(),
+           scheduleId.c_str());
+
+    if (mInfoByScheduleIdByClientId.find(clientId) == mInfoByScheduleIdByClientId.end()) {
+        response->set_istaskscheduled(false);
+        return Status::OK;
+    }
+    if (mInfoByScheduleIdByClientId[clientId].find(scheduleId) ==
+        mInfoByScheduleIdByClientId[clientId].end()) {
+        response->set_istaskscheduled(false);
+        return Status::OK;
+    }
+    response->set_istaskscheduled(true);
+    return Status::OK;
+}
+
+Status TestWakeupClientServiceImpl::GetAllScheduledTasks(ServerContext* context,
+                                                         const GetAllScheduledTasksRequest* request,
+                                                         GetAllScheduledTasksResponse* response) {
+    const std::string& clientId = request->clientid();
+    printf("GetAllScheduledTasks called with client Id: %s\n", clientId.c_str());
+    response->clear_allscheduledtasks();
+    {
+        std::unique_lock lk(mLock);
+        if (mInfoByScheduleIdByClientId.find(clientId) == mInfoByScheduleIdByClientId.end()) {
+            return Status::OK;
+        }
+        for (const auto& [_, scheduleInfo] : mInfoByScheduleIdByClientId[clientId]) {
+            (*response->add_allscheduledtasks()) = *scheduleInfo.grpcScheduleInfo;
+        }
+    }
+    return Status::OK;
+}
+
 bool TestWakeupClientServiceImpl::isWakeupRequired() {
     return mWakeupRequired;
 }
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
index be285a8..5443ad9 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
@@ -101,13 +101,17 @@
 #endif
 }
 
-const char* getSetPropCommand(int propId) {
-    int size = snprintf(nullptr, 0, COMMAND_SET_VHAL_PROP, propId, 1);
+const char* getSetPropCommand(int propId, int value) {
+    int size = snprintf(nullptr, 0, COMMAND_SET_VHAL_PROP, propId, value);
     char* command = new char[size + 1];
-    snprintf(command, size + 1, COMMAND_SET_VHAL_PROP, propId, 1);
+    snprintf(command, size + 1, COMMAND_SET_VHAL_PROP, propId, value);
     return command;
 }
 
+const char* getSetPropCommand(int propId) {
+    return getSetPropCommand(propId, /*value=*/1);
+}
+
 void powerOffEmu() {
     updateEmuStatus();
     if (emuPid == 0) {
@@ -136,7 +140,7 @@
     if (vehicleInUse) {
         value = 1;
     }
-    const char* command = getSetPropCommand(VEHICLE_IN_USE);
+    const char* command = getSetPropCommand(VEHICLE_IN_USE, value);
     runCommand(command);
     delete[] command;
 #else
diff --git a/automotive/remoteaccess/test_grpc_server/impl/test/TestWakeupClientServiceImplUnitTest.cpp b/automotive/remoteaccess/test_grpc_server/impl/test/TestWakeupClientServiceImplUnitTest.cpp
new file mode 100644
index 0000000..960020d
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/impl/test/TestWakeupClientServiceImplUnitTest.cpp
@@ -0,0 +1,339 @@
+/*
+ * 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 "TestWakeupClientServiceImpl.h"
+
+#include <grpcpp/channel.h>
+#include <grpcpp/create_channel.h>
+#include <grpcpp/security/credentials.h>
+#include <grpcpp/security/server_credentials.h>
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
+#include <gtest/gtest.h>
+#include <chrono>
+
+namespace android::hardware::automotive::remoteaccess::test {
+
+using ::android::base::ScopedLockAssertion;
+
+using ::grpc::Channel;
+using ::grpc::ClientContext;
+using ::grpc::Server;
+using ::grpc::ServerBuilder;
+using ::grpc::Status;
+
+const std::string kTestClientId = "test client id";
+const std::string kTestScheduleId = "test schedule id";
+const std::vector<uint8_t> kTestData = {0xde, 0xad, 0xbe, 0xef};
+constexpr int32_t kTestCount = 1234;
+constexpr int64_t kTestStartTimeInEpochSeconds = 2345;
+constexpr int64_t kTestPeriodicInSeconds = 123;
+const std::string kTestGrpcAddr = "localhost:50051";
+
+class MyTestWakeupClientServiceImpl final : public TestWakeupClientServiceImpl {
+  public:
+    void wakeupApplicationProcessor() override {
+        // Do nothing.
+    }
+};
+
+class TestWakeupClientServiceImplUnitTest : public ::testing::Test {
+  public:
+    virtual void SetUp() override {
+        mServerThread = std::thread([this] {
+            {
+                std::unique_lock<std::mutex> lock(mLock);
+                mService = std::make_unique<MyTestWakeupClientServiceImpl>();
+                ServerBuilder builder;
+                builder.AddListeningPort(kTestGrpcAddr, grpc::InsecureServerCredentials());
+                builder.RegisterService(mService.get());
+                mServer = builder.BuildAndStart();
+                mServerStartCv.notify_one();
+            }
+            mServer->Wait();
+        });
+        {
+            std::unique_lock<std::mutex> lock(mLock);
+            mServerStartCv.wait(lock, [this] {
+                ScopedLockAssertion lockAssertion(mLock);
+                return mServer != nullptr;
+            });
+        }
+        mChannel = grpc::CreateChannel(kTestGrpcAddr, grpc::InsecureChannelCredentials());
+        mStub = WakeupClient::NewStub(mChannel);
+    }
+
+    virtual void TearDown() override {
+        printf("Start server shutdown\n");
+        mService->stopServer();
+        mServer->Shutdown();
+        printf("Server shutdown complete\n");
+        mServerThread.join();
+        printf("Server thread exits\n");
+        mServer.reset();
+        mService.reset();
+        printf("Server and service classes reset\n");
+    }
+
+    WakeupClient::Stub* getStub() { return mStub.get(); }
+
+    size_t waitForRemoteTasks(size_t count) {
+        ClientContext context = {};
+        GetRemoteTasksResponse response;
+        auto reader = mStub->GetRemoteTasks(&context, GetRemoteTasksRequest{});
+        size_t got = 0;
+        while (reader->Read(&response)) {
+            got++;
+            mRemoteTaskResponses.push_back(response);
+            if (got == count) {
+                break;
+            }
+        }
+        // If there is more messages to be read in the reader, cancel them all so that we can
+        // finish.
+        context.TryCancel();
+        reader->Finish();
+        return got;
+    }
+
+    std::vector<GetRemoteTasksResponse> getRemoteTaskResponses() { return mRemoteTaskResponses; }
+
+    Status scheduleTask(int32_t count, int64_t startTimeInEpochSeconds, int64_t periodicInSeconds) {
+        return scheduleTask(kTestScheduleId, count, startTimeInEpochSeconds, periodicInSeconds);
+    }
+
+    Status scheduleTask(const std::string& scheduleId, int32_t count,
+                        int64_t startTimeInEpochSeconds, int64_t periodicInSeconds) {
+        ClientContext context;
+        ScheduleTaskRequest request;
+        ScheduleTaskResponse response;
+        int64_t now = std::chrono::duration_cast<std::chrono::seconds>(
+                              std::chrono::system_clock::now().time_since_epoch())
+                              .count();
+        request.mutable_scheduleinfo()->set_clientid(kTestClientId);
+        request.mutable_scheduleinfo()->set_scheduleid(scheduleId);
+        request.mutable_scheduleinfo()->set_data(kTestData.data(), kTestData.size());
+        request.mutable_scheduleinfo()->set_count(count);
+        request.mutable_scheduleinfo()->set_starttimeinepochseconds(startTimeInEpochSeconds);
+        request.mutable_scheduleinfo()->set_periodicinseconds(periodicInSeconds);
+
+        return getStub()->ScheduleTask(&context, request, &response);
+    }
+
+    int64_t getNow() {
+        return std::chrono::duration_cast<std::chrono::seconds>(
+                       std::chrono::system_clock::now().time_since_epoch())
+                .count();
+    }
+
+  private:
+    std::condition_variable mServerStartCv;
+    std::mutex mLock;
+    std::thread mServerThread;
+    std::unique_ptr<MyTestWakeupClientServiceImpl> mService;
+    std::unique_ptr<Server> mServer;
+    std::shared_ptr<Channel> mChannel;
+    std::unique_ptr<WakeupClient::Stub> mStub;
+    std::vector<GetRemoteTasksResponse> mRemoteTaskResponses;
+};
+
+TEST_F(TestWakeupClientServiceImplUnitTest, TestScheduleTask) {
+    ClientContext context = {};
+    ScheduleTaskRequest request = {};
+    ScheduleTaskResponse response = {};
+
+    request.mutable_scheduleinfo()->set_clientid(kTestClientId);
+    request.mutable_scheduleinfo()->set_scheduleid(kTestScheduleId);
+    request.mutable_scheduleinfo()->set_data(kTestData.data(), kTestData.size());
+    request.mutable_scheduleinfo()->set_count(2);
+    // Schedule the task to be executed 1s later.
+    request.mutable_scheduleinfo()->set_starttimeinepochseconds(getNow() + 1);
+    request.mutable_scheduleinfo()->set_periodicinseconds(1);
+
+    Status status = getStub()->ScheduleTask(&context, request, &response);
+
+    ASSERT_TRUE(status.ok());
+    ASSERT_EQ(response.errorcode(), ErrorCode::OK);
+
+    size_t gotTaskCount = waitForRemoteTasks(/*count=*/2);
+
+    EXPECT_EQ(gotTaskCount, 2);
+    auto responses = getRemoteTaskResponses();
+    for (const auto& response : responses) {
+        EXPECT_EQ(response.clientid(), kTestClientId);
+        EXPECT_EQ(response.data(), std::string(kTestData.begin(), kTestData.end()));
+    }
+}
+
+TEST_F(TestWakeupClientServiceImplUnitTest, TestScheduleTask_conflictScheduleId) {
+    Status status = scheduleTask(/*count=*/2, /*startTimeInEpochSeconds=*/getNow() + 1,
+                                 /*periodicInSeconds=*/1);
+
+    ASSERT_TRUE(status.ok());
+
+    // Schedule the same task again.
+    ClientContext context = {};
+    ScheduleTaskRequest request = {};
+    ScheduleTaskResponse response = {};
+
+    request.mutable_scheduleinfo()->set_clientid(kTestClientId);
+    request.mutable_scheduleinfo()->set_scheduleid(kTestScheduleId);
+    request.mutable_scheduleinfo()->set_data(kTestData.data(), kTestData.size());
+    request.mutable_scheduleinfo()->set_count(2);
+    request.mutable_scheduleinfo()->set_starttimeinepochseconds(getNow() + 1);
+    request.mutable_scheduleinfo()->set_periodicinseconds(1);
+
+    status = getStub()->ScheduleTask(&context, request, &response);
+
+    ASSERT_TRUE(status.ok());
+    ASSERT_EQ(response.errorcode(), ErrorCode::INVALID_ARG);
+}
+
+TEST_F(TestWakeupClientServiceImplUnitTest, TestUnscheduleTask) {
+    Status status = scheduleTask(/*count=*/2, /*startTimeInEpochSeconds=*/getNow() + 1,
+                                 /*periodicInSeconds=*/1);
+
+    ASSERT_TRUE(status.ok());
+
+    ClientContext context;
+    UnscheduleTaskRequest request;
+    UnscheduleTaskResponse response;
+    request.set_clientid(kTestClientId);
+    request.set_scheduleid(kTestScheduleId);
+    status = getStub()->UnscheduleTask(&context, request, &response);
+
+    ASSERT_TRUE(status.ok());
+
+    sleep(2);
+
+    // There should be no remote tasks received after 2s because the task was unscheduled.
+    EXPECT_EQ(getRemoteTaskResponses().size(), 0);
+}
+
+TEST_F(TestWakeupClientServiceImplUnitTest, TestIsTaskScheduled) {
+    int64_t startTimeInEpochSeconds = getNow() + 1;
+    int64_t periodicInSeconds = 1234;
+
+    Status status = scheduleTask(/*count=*/2, startTimeInEpochSeconds, periodicInSeconds);
+
+    ASSERT_TRUE(status.ok());
+
+    ClientContext context;
+    IsTaskScheduledRequest request;
+    IsTaskScheduledResponse response;
+    request.set_clientid(kTestClientId);
+    request.set_scheduleid(kTestScheduleId);
+    status = getStub()->IsTaskScheduled(&context, request, &response);
+
+    ASSERT_TRUE(status.ok());
+    EXPECT_TRUE(response.istaskscheduled());
+
+    ClientContext context2;
+    IsTaskScheduledRequest request2;
+    IsTaskScheduledResponse response2;
+    request.set_clientid(kTestClientId);
+    request.set_scheduleid("invalid id");
+    status = getStub()->IsTaskScheduled(&context2, request2, &response2);
+
+    ASSERT_TRUE(status.ok());
+    EXPECT_FALSE(response2.istaskscheduled());
+}
+
+TEST_F(TestWakeupClientServiceImplUnitTest, TestUnscheduleAllTasks) {
+    std::string scheduleId1 = "scheduleId1";
+    std::string scheduleId2 = "scheduleId2";
+    int64_t time1 = getNow();
+    int64_t time2 = getNow() + 1;
+    int64_t periodicInSeconds1 = 1;
+    int64_t periodicInSeconds2 = 1;
+    int32_t count1 = 2;
+    int64_t count2 = 5;
+
+    Status status = scheduleTask(scheduleId1, count1, time1, periodicInSeconds1);
+    ASSERT_TRUE(status.ok());
+    status = scheduleTask(scheduleId2, count2, time2, periodicInSeconds2);
+    ASSERT_TRUE(status.ok());
+
+    ClientContext context;
+    UnscheduleAllTasksRequest request;
+    UnscheduleAllTasksResponse response;
+    request.set_clientid(kTestClientId);
+    status = getStub()->UnscheduleAllTasks(&context, request, &response);
+    ASSERT_TRUE(status.ok());
+
+    sleep(2);
+
+    // There should be no remote tasks received after 2s because the tasks were unscheduled.
+    EXPECT_EQ(getRemoteTaskResponses().size(), 0);
+}
+
+TEST_F(TestWakeupClientServiceImplUnitTest, TestGetAllScheduledTasks) {
+    std::string scheduleId1 = "scheduleId1";
+    std::string scheduleId2 = "scheduleId2";
+    int64_t time1 = getNow();
+    int64_t time2 = getNow() + 1;
+    int64_t periodicInSeconds1 = 1;
+    int64_t periodicInSeconds2 = 1;
+    int32_t count1 = 2;
+    int64_t count2 = 5;
+
+    Status status = scheduleTask(scheduleId1, count1, time1, periodicInSeconds1);
+    ASSERT_TRUE(status.ok());
+    status = scheduleTask(scheduleId2, count2, time2, periodicInSeconds2);
+    ASSERT_TRUE(status.ok());
+
+    ClientContext context;
+    GetAllScheduledTasksRequest request;
+    GetAllScheduledTasksResponse response;
+    request.set_clientid("invalid client Id");
+    status = getStub()->GetAllScheduledTasks(&context, request, &response);
+
+    ASSERT_TRUE(status.ok());
+    EXPECT_EQ(response.allscheduledtasks_size(), 0);
+
+    ClientContext context2;
+    GetAllScheduledTasksRequest request2;
+    GetAllScheduledTasksResponse response2;
+    request2.set_clientid(kTestClientId);
+    status = getStub()->GetAllScheduledTasks(&context2, request2, &response2);
+
+    ASSERT_TRUE(status.ok());
+    ASSERT_EQ(response2.allscheduledtasks_size(), 2);
+    for (int i = 0; i < 2; i++) {
+        EXPECT_EQ(response2.allscheduledtasks(i).clientid(), kTestClientId);
+        if (response2.allscheduledtasks(i).scheduleid() == scheduleId1) {
+            EXPECT_EQ(response2.allscheduledtasks(i).data(),
+                      std::string(kTestData.begin(), kTestData.end()));
+            EXPECT_EQ(response2.allscheduledtasks(i).count(), count1);
+            EXPECT_EQ(response2.allscheduledtasks(i).starttimeinepochseconds(), time1);
+            EXPECT_EQ(response2.allscheduledtasks(i).periodicinseconds(), periodicInSeconds1);
+        } else {
+            EXPECT_EQ(response2.allscheduledtasks(i).scheduleid(), scheduleId2);
+            EXPECT_EQ(response2.allscheduledtasks(i).data(),
+                      std::string(kTestData.begin(), kTestData.end()));
+            EXPECT_EQ(response2.allscheduledtasks(i).count(), count2);
+            EXPECT_EQ(response2.allscheduledtasks(i).starttimeinepochseconds(), time2);
+            EXPECT_EQ(response2.allscheduledtasks(i).periodicinseconds(), periodicInSeconds2);
+        }
+    }
+}
+
+}  // namespace android::hardware::automotive::remoteaccess::test
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/biometrics/face/aidl/default/Android.bp b/biometrics/face/aidl/default/Android.bp
index 7bc2198..b005746 100644
--- a/biometrics/face/aidl/default/Android.bp
+++ b/biometrics/face/aidl/default/Android.bp
@@ -23,13 +23,10 @@
     init_rc: [":face-example.rc"],
     vintf_fragments: [":face-example.xml"],
     vendor: true,
+
     shared_libs: [
-        "libbase",
         "libbinder_ndk",
-        "android.hardware.biometrics.face-V3-ndk",
-        "android.hardware.biometrics.common-V3-ndk",
-        "android.hardware.biometrics.common.thread",
-        "android.hardware.biometrics.common.util",
+        "liblog",
     ],
     srcs: [
         "main.cpp",
@@ -37,7 +34,17 @@
         "FakeFaceEngine.cpp",
         "Session.cpp",
     ],
-    static_libs: ["libandroid.hardware.biometrics.face.VirtualProps"],
+    stl: "c++_static",
+    static_libs: [
+        "android.hardware.biometrics.common-V3-ndk",
+        "android.hardware.biometrics.common.thread",
+        "android.hardware.biometrics.common.util",
+        "android.hardware.biometrics.face-V3-ndk",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.keymaster-V4-ndk",
+        "libandroid.hardware.biometrics.face.VirtualProps",
+        "libbase",
+    ],
 }
 
 sysprop_library {
diff --git a/biometrics/fingerprint/aidl/default/apex/Android.bp b/biometrics/fingerprint/aidl/default/apex/Android.bp
index ad36ae2..75d84a9 100644
--- a/biometrics/fingerprint/aidl/default/apex/Android.bp
+++ b/biometrics/fingerprint/aidl/default/apex/Android.bp
@@ -16,25 +16,13 @@
     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",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
     updatable: false,
-    use_vndk_as_stable: true,
     vendor: true,
 
     binaries: [
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/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
index 1028fae..feed6f5 100644
--- a/bluetooth/audio/aidl/Android.bp
+++ b/bluetooth/audio/aidl/Android.bp
@@ -27,10 +27,12 @@
     host_supported: true,
     srcs: ["android/hardware/bluetooth/audio/*.aidl"],
     stability: "vintf",
+    defaults: [
+        "latest_android_hardware_audio_common_import_interface",
+    ],
     imports: [
         "android.hardware.common-V2",
         "android.hardware.common.fmq-V1",
-        "android.hardware.audio.common-V2",
     ],
     backend: {
         cpp: {
@@ -75,6 +77,23 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
+
+// Note: This should always be one version ahead of the last frozen version
+latest_android_hardware_bluetooth_audio = "android.hardware.bluetooth.audio-V4"
+
+cc_defaults {
+    name: "latest_android_hardware_bluetooth_audio_ndk_shared",
+    shared_libs: [
+        latest_android_hardware_bluetooth_audio + "-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "latest_android_hardware_bluetooth_audio_ndk_static",
+    static_libs: [
+        latest_android_hardware_bluetooth_audio + "-ndk",
+    ],
+}
diff --git a/bluetooth/audio/aidl/default/Android.bp b/bluetooth/audio/aidl/default/Android.bp
index e4c2844..40aea32 100644
--- a/bluetooth/audio/aidl/default/Android.bp
+++ b/bluetooth/audio/aidl/default/Android.bp
@@ -11,6 +11,9 @@
     name: "android.hardware.bluetooth.audio-impl",
     vendor: true,
     vintf_fragments: ["bluetooth_audio.xml"],
+    defaults: [
+        "latest_android_hardware_bluetooth_audio_ndk_shared",
+    ],
     srcs: [
         "BluetoothAudioProvider.cpp",
         "BluetoothAudioProviderFactory.cpp",
@@ -29,7 +32,6 @@
         "libcutils",
         "libfmq",
         "liblog",
-        "android.hardware.bluetooth.audio-V3-ndk",
         "libbluetooth_audio_session_aidl",
     ],
 }
diff --git a/bluetooth/audio/aidl/default/bluetooth_audio.xml b/bluetooth/audio/aidl/default/bluetooth_audio.xml
index c0bc55e..3561dd1 100644
--- a/bluetooth/audio/aidl/default/bluetooth_audio.xml
+++ b/bluetooth/audio/aidl/default/bluetooth_audio.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.bluetooth.audio</name>
-        <version>3</version>
+        <version>4</version>
         <fqname>IBluetoothAudioProviderFactory/default</fqname>
     </hal>
 </manifest>
diff --git a/bluetooth/audio/aidl/vts/Android.bp b/bluetooth/audio/aidl/vts/Android.bp
index fa85fa8..884062a 100644
--- a/bluetooth/audio/aidl/vts/Android.bp
+++ b/bluetooth/audio/aidl/vts/Android.bp
@@ -10,17 +10,17 @@
 cc_test {
     name: "VtsHalBluetoothAudioTargetTest",
     defaults: [
+        "latest_android_hardware_audio_common_ndk_static",
+        "latest_android_hardware_bluetooth_audio_ndk_static",
+        "latest_android_media_audio_common_types_ndk_static",
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
     tidy_timeout_srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
     srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
     static_libs: [
-        "android.hardware.audio.common-V2-ndk",
-        "android.hardware.bluetooth.audio-V3-ndk",
         "android.hardware.common-V2-ndk",
         "android.hardware.common.fmq-V1-ndk",
-        "android.media.audio.common.types-V2-ndk",
     ],
     shared_libs: [
         "libbase",
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index a09e7fe..75081d6 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -48,6 +48,9 @@
         "libhardware_headers",
         "libxsdc-utils",
     ],
+    defaults: [
+        "latest_android_hardware_bluetooth_audio_ndk_shared",
+    ],
     shared_libs: [
         "android.hardware.bluetooth.audio@2.0",
         "android.hardware.bluetooth.audio@2.1",
@@ -56,7 +59,6 @@
         "libbinder_ndk",
         "libfmq",
         "liblog",
-        "android.hardware.bluetooth.audio-V3-ndk",
         "libhidlbase",
         "libxml2",
     ],
diff --git a/cas/aidl/default/Android.bp b/cas/aidl/default/Android.bp
index 9d094e0..34ecbf2 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"],
 }
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/common/aidl/Android.bp b/common/aidl/Android.bp
index f3ea8e8..1457b8a 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -38,7 +38,7 @@
         },
         rust: {
             enabled: true,
-        }
+        },
     },
     frozen: true,
     versions: [
diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml
index 2a1f4a5..9057788 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 a69def8..75915e3 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -19,7 +19,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.audio.core</name>
-        <version>1</version>
+        <version>1-2</version>
         <interface>
             <name>IModule</name>
             <instance>default</instance>
@@ -38,7 +38,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.audio.effect</name>
-        <version>1</version>
+        <version>1-2</version>
         <interface>
             <name>IFactory</name>
             <instance>default</instance>
@@ -46,7 +46,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.audio.sounddose</name>
-        <version>1</version>
+        <version>1-2</version>
         <interface>
             <name>ISoundDoseFactory</name>
             <instance>default</instance>
@@ -62,7 +62,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.automotive.audiocontrol</name>
-        <version>2-3</version>
+        <version>2-4</version>
         <interface>
             <name>IAudioControl</name>
             <instance>default</instance>
@@ -142,7 +142,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.bluetooth.audio</name>
-        <version>3</version>
+        <version>3-4</version>
         <interface>
             <name>IBluetoothAudioProviderFactory</name>
             <instance>default</instance>
@@ -537,7 +537,7 @@
     </hal>
     <hal format="aidl" optional="true">
          <name>android.hardware.soundtrigger3</name>
-         <version>1</version>
+         <version>1-2</version>
          <interface>
              <name>ISoundTriggerHw</name>
              <instance>default</instance>
@@ -601,7 +601,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.tv.input</name>
-        <version>1</version>
+        <version>1-2</version>
         <interface>
             <name>ITvInput</name>
             <instance>default</instance>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index d92c0b9..2cb4ffa 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -142,6 +142,7 @@
 
             // AIDL
             "android.hardware.audio.core.sounddose@1",
+            "android.hardware.audio.core.sounddose@2",
 
             // Deprecated HALs.
             "android.hardware.bluetooth.audio@1",
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
index 57d0e68..f6a8fef 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
@@ -63,7 +63,12 @@
       BDS_CNAV2 = 0x0504,
       GAL_I = 0x0601,
       GAL_F = 0x0602,
+      /**
+       * @deprecated Use IRN_L5 instead.
+       */
       IRN_L5CA = 0x0701,
+      IRN_L5 = 0x0702,
+      IRN_L1 = 0x0703,
     }
   }
 }
diff --git a/gnss/aidl/android/hardware/gnss/IGnssNavigationMessageCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
index 6990e19..b224b0b 100644
--- a/gnss/aidl/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnssNavigationMessageCallback.aidl
@@ -100,8 +100,17 @@
             /** Galileo F/NAV message contained in the structure. */
             GAL_F = 0x0602,
 
-            /** IRNSS L5 C/A message contained in the structure. */
+            /**
+             * NavIC L5 C/A message contained in the structure.
+             * @deprecated Use IRN_L5 instead.
+             */
             IRN_L5CA = 0x0701,
+
+            /** NavIC L5 message contained in the structure. */
+            IRN_L5 = 0x0702,
+
+            /** NavIC L1 message contained in the structure. */
+            IRN_L1 = 0x0703,
         }
 
         /**
@@ -156,9 +165,12 @@
          *
          * - For Beidou CNAV1 this refers to the page type number in the range of 1-63.
          *
-         * - For IRNSS L5 C/A subframe 3 and 4, this value corresponds to the Message Id of the
+         * - For NavIC L5 subframe 3 and 4, this value corresponds to the Message Id of the
          *   navigation message, in the range of 1-63. (Subframe 1 and 2 does not contain a message
          *   type id and this value can be set to -1.)
+         * - For NavIC L1 subframe 3, this value corresponds to the Message Id of the navigation
+         *   message, in the range of 1-63. (Subframe 1 and 2 does not contain a message type id and
+         *   this value can be set to -1.)
          */
         int messageId;
 
@@ -187,8 +199,10 @@
          *
          * - For Beidou CNAV2, the submessage id corresponds to the message type, in the range 1-63.
          *
-         * - For IRNSS L5 C/A, the submessage id corresponds to the subframe number of the
-         *   navigation message, in the range of 1-4.
+         * - For NavIC L5, the submessage id corresponds to the subframe number of the navigation
+         *   message, in the range of 1-4.
+         * - For NavIC L1, the submessage id corresponds to the subframe number of the navigation
+         *   message, in the range of 1-3.
          */
         int submessageId;
 
@@ -196,7 +210,7 @@
          * The data of the reported GNSS message. The bytes (or words) are specified
          * using big endian format (MSB first).
          *
-         * - For GNSS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+         * - For GNSS L1 C/A, NavIC L5, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
          *   words. Each word (30 bits) must fit into the last 30 bits in a
          *   4-byte word (skip B31 and B32), with MSB first, for a total of 40
          *   bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
@@ -228,6 +242,10 @@
          * - For Beidou CNAV2, each subframe consists of 288 data bits, that should be fit into 36
          *   bytes.
          *
+         * - For NavIC L1, subframe #1 consists of 9 data bits that should be fit into 2 bytes (skip
+         *   B10-B16). subframe #2 consists of 600 bits that should be fit into 75 bytes. subframe
+         *   #3 consists of 274 data bits that should be fit into 35 bytes (skip B275-B280).
+         *
          * The data reported here must be the raw data as demodulated by the GNSS receiver, not data
          * received from an external source (i.e. not from a server download.)
          */
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
index 6eba887..0e2d72b 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
@@ -42,4 +42,5 @@
   AUTO_LOW_LATENCY_MODE = 5,
   SUSPEND = 6,
   DISPLAY_IDLE_TIMER = 7,
+  MULTI_THREADED_PRESENT = 8,
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
index f4b2984..7154d74 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
@@ -80,4 +80,20 @@
      * IComposerCallback.onVsyncIdle.
      */
     DISPLAY_IDLE_TIMER = 7,
+    /**
+     * Indicates that both the composer HAL implementation and the given display
+     * support calling executeCommands concurrently from separate threads.
+     * executeCommands for a particular display will never run concurrently to
+     * any other executeCommands for the same display. In addition, the
+     * CommandResultPayload must only reference displays included in the
+     * DisplayCommands passed to executeCommands. Displays referenced from
+     * separate threads must have minimal interference with one another. If a
+     * HWC-managed display has this capability, SurfaceFlinger can run
+     * executeCommands for this display concurrently with other displays with the
+     * same capability.
+     * @see IComposerClient.executeCommands
+     * @see DisplayCommand.presentDisplay
+     * @see DisplayCommand.validateDisplay
+     */
+    MULTI_THREADED_PRESENT = 8,
 }
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index 09882f5..6d74951 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -34,6 +34,7 @@
 #include <ui/PixelFormat.h>
 #include <algorithm>
 #include <iterator>
+#include <mutex>
 #include <numeric>
 #include <string>
 #include <thread>
@@ -1381,21 +1382,17 @@
     void execute() {
         std::vector<CommandResultPayload> payloads;
         for (auto& [_, writer] : mWriters) {
-            auto commands = writer.takePendingCommands();
-            if (commands.empty()) {
-                continue;
-            }
-
-            auto [status, results] = mComposerClient->executeCommands(commands);
-            ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
-
-            payloads.reserve(payloads.size() + results.size());
-            payloads.insert(payloads.end(), std::make_move_iterator(results.begin()),
-                            std::make_move_iterator(results.end()));
+            executeInternal(writer, payloads);
         }
         mReader.parse(std::move(payloads));
     }
 
+    void execute(ComposerClientWriter& writer, ComposerClientReader& reader) {
+        std::vector<CommandResultPayload> payloads;
+        executeInternal(writer, payloads);
+        reader.parse(std::move(payloads));
+    }
+
     static inline auto toTimePoint(nsecs_t time) {
         return std::chrono::time_point<std::chrono::steady_clock>(std::chrono::nanoseconds(time));
     }
@@ -1720,6 +1717,7 @@
     // clang-format on
 
     ComposerClientWriter& getWriter(int64_t display) {
+        std::lock_guard guard{mWritersMutex};
         auto [it, _] = mWriters.try_emplace(display, display);
         return it->second;
     }
@@ -1727,7 +1725,27 @@
     ComposerClientReader mReader;
 
   private:
-    std::unordered_map<int64_t, ComposerClientWriter> mWriters;
+    void executeInternal(ComposerClientWriter& writer,
+                         std::vector<CommandResultPayload>& payloads) {
+        auto commands = writer.takePendingCommands();
+        if (commands.empty()) {
+            return;
+        }
+
+        auto [status, results] = mComposerClient->executeCommands(commands);
+        ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
+
+        payloads.reserve(payloads.size() + results.size());
+        payloads.insert(payloads.end(), std::make_move_iterator(results.begin()),
+                        std::make_move_iterator(results.end()));
+    }
+
+    // Guards access to the map itself. Callers must ensure not to attempt to
+    // - modify the same writer from multiple threads
+    // - insert a new writer into the map during concurrent access, which would invalidate
+    //   references from other threads
+    std::mutex mWritersMutex;
+    std::unordered_map<int64_t, ComposerClientWriter> mWriters GUARDED_BY(mWritersMutex);
 };
 
 TEST_P(GraphicsComposerAidlCommandTest, SetColorTransform) {
@@ -2784,6 +2802,106 @@
     }
 }
 
+TEST_P(GraphicsComposerAidlCommandTest, MultiThreadedPresent) {
+    std::vector<VtsDisplay*> displays;
+    for (auto& display : mDisplays) {
+        if (hasDisplayCapability(display.getDisplayId(),
+                                 DisplayCapability::MULTI_THREADED_PRESENT)) {
+            displays.push_back(&display);
+        }
+    }
+
+    const size_t numDisplays = displays.size();
+    if (numDisplays <= 1u) {
+        GTEST_SKIP();
+    }
+
+    // When multi-threaded, use a reader per display. As with mWriters, this mutex
+    // guards access to the map.
+    std::mutex readersMutex;
+    std::unordered_map<int64_t, ComposerClientReader> readers;
+    std::vector<std::thread> threads;
+    threads.reserve(numDisplays);
+
+    // Each display will have a layer to present. This maps from the display to
+    // the layer, so we can properly destroy each layer at the end.
+    std::unordered_map<int64_t, int64_t> layers;
+
+    for (auto* const display : displays) {
+        const int64_t displayId = display->getDisplayId();
+
+        // Ensure that all writers and readers have been added to their respective
+        // maps initially, so that the following loop never modifies the maps. The
+        // maps are accessed from different threads, and if the maps were modified,
+        // this would invalidate their iterators, and therefore references to the
+        // writers and readers.
+        auto& writer = getWriter(displayId);
+        {
+            std::lock_guard guard{readersMutex};
+            readers.try_emplace(displayId, displayId);
+        }
+
+        EXPECT_TRUE(mComposerClient->setPowerMode(displayId, PowerMode::ON).isOk());
+
+        const auto& [status, layer] = mComposerClient->createLayer(displayId, kBufferSlotCount);
+        const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+        ASSERT_NE(nullptr, buffer);
+        ASSERT_EQ(::android::OK, buffer->initCheck());
+        ASSERT_NE(nullptr, buffer->handle);
+
+        configureLayer(*display, layer, Composition::DEVICE, display->getFrameRect(),
+                       display->getCrop());
+        writer.setLayerBuffer(displayId, layer, /*slot*/ 0, buffer->handle,
+                              /*acquireFence*/ -1);
+        writer.setLayerDataspace(displayId, layer, common::Dataspace::UNKNOWN);
+        layers.try_emplace(displayId, layer);
+    }
+
+    for (auto* const display : displays) {
+        const int64_t displayId = display->getDisplayId();
+        auto& writer = getWriter(displayId);
+        std::unique_lock lock{readersMutex};
+        auto& reader = readers.at(displayId);
+        lock.unlock();
+
+        writer.validateDisplay(displayId, ComposerClientWriter::kNoTimestamp);
+        execute(writer, reader);
+
+        threads.emplace_back([this, displayId, &readers, &readersMutex]() {
+            auto& writer = getWriter(displayId);
+            std::unique_lock lock{readersMutex};
+            ComposerClientReader& reader = readers.at(displayId);
+            lock.unlock();
+
+            writer.presentDisplay(displayId);
+            execute(writer, reader);
+            ASSERT_TRUE(reader.takeErrors().empty());
+
+            auto presentFence = reader.takePresentFence(displayId);
+            // take ownership
+            const int fenceOwner = presentFence.get();
+            *presentFence.getR() = -1;
+            EXPECT_NE(-1, fenceOwner);
+            const auto presentFence2 = sp<::android::Fence>::make(fenceOwner);
+            presentFence2->waitForever(LOG_TAG);
+        });
+    }
+
+    for (auto& thread : threads) {
+        thread.join();
+    }
+
+    for (auto& [displayId, layer] : layers) {
+        EXPECT_TRUE(mComposerClient->destroyLayer(displayId, layer).isOk());
+    }
+
+    std::lock_guard guard{readersMutex};
+    for (auto& [displayId, reader] : readers) {
+        ASSERT_TRUE(reader.takeErrors().empty());
+        ASSERT_TRUE(reader.takeChangedCompositionTypes(displayId).empty());
+    }
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandTest);
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, GraphicsComposerAidlCommandTest,
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/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
index d2d3137..782dbbf 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
@@ -51,4 +51,5 @@
   VSIM = (1 << 12) /* 4096 */,
   BIP = (1 << 13) /* 8192 */,
   ENTERPRISE = (1 << 14) /* 16384 */,
+  RCS = (1 << 15) /* 32768 */,
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
index bd44275..7f3fdc7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
@@ -55,6 +55,7 @@
   boolean persistent;
   boolean alwaysOn;
   android.hardware.radio.data.TrafficDescriptor trafficDescriptor;
+  int infrastructureBitmap = INFRASTRUCTURE_UNKNOWN /* 0 */;
   const int ID_DEFAULT = 0;
   const int ID_TETHERED = 1;
   const int ID_IMS = 2;
@@ -65,4 +66,7 @@
   const int TYPE_COMMON = 0;
   const int TYPE_3GPP = 1;
   const int TYPE_3GPP2 = 2;
+  const int INFRASTRUCTURE_UNKNOWN = 0;
+  const int INFRASTRUCTURE_CELLULAR = (1 << 0) /* 1 */;
+  const int INFRASTRUCTURE_SATELLITE = (1 << 1) /* 2 */;
 }
diff --git a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
index 366570a..f44c636 100644
--- a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
@@ -86,5 +86,9 @@
     /**
      * APN type for ENTERPRISE
      */
-    ENTERPRISE = 1 << 14
+    ENTERPRISE = 1 << 14,
+    /**
+     * APN type for RCS (Rich Communication Services)
+     */
+    RCS = 1 << 15
 }
diff --git a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
index 613387f..d01f8ff 100644
--- a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
@@ -40,6 +40,21 @@
     const int TYPE_3GPP2 = 2;
 
     /**
+     * Innfrastructure type unknown. This is only for initializing.
+     */
+    const int INFRASTRUCTURE_UNKNOWN = 0;
+
+    /**
+     * Indicating this APN can be used when the device is using terrestrial cellular networks.
+     */
+    const int INFRASTRUCTURE_CELLULAR = 1 << 0;
+
+    /**
+     * Indicating this APN can be used when the device is attached to satellite.
+     */
+    const int INFRASTRUCTURE_SATELLITE = 1 << 1;
+
+    /**
      * ID of the data profile.
      * Values are ID_
      */
@@ -131,4 +146,10 @@
      * apn; apn must be used as the end point if one is not specified through URSP rules.
      */
     TrafficDescriptor trafficDescriptor;
+    /**
+     * The infrastructure bitmap which the APN can be used on. For example, some APNs can only
+     * be used when the device is using cellular network, using satellite network, or can be used
+     * in either cases.
+     */
+    int infrastructureBitmap = INFRASTRUCTURE_UNKNOWN;
 }
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index db37a0e..0889832 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -623,7 +623,6 @@
      *   RadioError:NONE
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:MODEM_ERR
-     *   RadioError:REQUEST_NOT_SUPPORTED
      */
     void setNullCipherAndIntegrityEnabledResponse(in RadioResponseInfo info);
 
@@ -635,7 +634,6 @@
      *   RadioError:NONE
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:MODEM_ERR
-     *   RadioError:REQUEST_NOT_SUPPORTED
      */
     void isNullCipherAndIntegrityEnabledResponse(in RadioResponseInfo info, in boolean isEnabled);
 
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
index 6643c1e..4e84116 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -1931,9 +1931,9 @@
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
 
-    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
-                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
-                                  RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_network->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
 }
 
 /**
@@ -1958,7 +1958,7 @@
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
 
-    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
-                                 {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
-                                  RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED}));
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_network->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
 }
diff --git a/sensors/aidl/vts/SensorsAidlTestSharedMemory.h b/sensors/aidl/vts/SensorsAidlTestSharedMemory.h
index 4b5916a..200f26f 100644
--- a/sensors/aidl/vts/SensorsAidlTestSharedMemory.h
+++ b/sensors/aidl/vts/SensorsAidlTestSharedMemory.h
@@ -17,7 +17,11 @@
 #ifndef ANDROID_SENSORS_AIDL_TEST_SHARED_MEMORY_H
 #define ANDROID_SENSORS_AIDL_TEST_SHARED_MEMORY_H
 
-#include "sensors-vts-utils/GrallocWrapper.h"
+#include <aidl/android/hardware/graphics/common/BufferUsage.h>
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBufferMapper.h>
 
 #include <aidlcommonsupport/NativeHandle.h>
 #include <android-base/macros.h>
@@ -28,6 +32,8 @@
 
 #include <cutils/ashmem.h>
 
+using ::aidl::android::hardware::graphics::common::BufferUsage;
+using ::aidl::android::hardware::graphics::common::PixelFormat;
 using ::aidl::android::hardware::sensors::BnSensors;
 using ::aidl::android::hardware::sensors::Event;
 using ::aidl::android::hardware::sensors::ISensors;
@@ -53,12 +59,22 @@
     }
 
     ISensors::SharedMemInfo getSharedMemInfo() const {
-        ISensors::SharedMemInfo mem = {
-                .type = mType,
-                .format = ISensors::SharedMemInfo::SharedMemFormat::SENSORS_EVENT,
-                .size = static_cast<int32_t>(mSize),
-                .memoryHandle = android::dupToAidl(mNativeHandle)};
-        return mem;
+        if (mType == ISensors::SharedMemInfo::SharedMemType::GRALLOC) {
+            ISensors::SharedMemInfo mem = {
+                    .type = mType,
+                    .format = ISensors::SharedMemInfo::SharedMemFormat::SENSORS_EVENT,
+                    .size = static_cast<int32_t>(mSize),
+                    .memoryHandle = android::dupToAidl(mBufferHandle)};
+            return mem;
+
+        } else {
+            ISensors::SharedMemInfo mem = {
+                    .type = mType,
+                    .format = ISensors::SharedMemInfo::SharedMemFormat::SENSORS_EVENT,
+                    .size = static_cast<int32_t>(mSize),
+                    .memoryHandle = android::dupToAidl(mNativeHandle)};
+            return mem;
+        }
     }
     char* getBuffer() const { return mBuffer; }
     size_t getSize() const { return mSize; }
@@ -141,17 +157,26 @@
             }
             case ISensors::SharedMemInfo::SharedMemType::GRALLOC: {
                 if (mSize != 0) {
-                    mGrallocWrapper->freeBuffer(mNativeHandle);
-                    mNativeHandle = nullptr;
+                    android::status_t status =
+                            android::GraphicBufferAllocator::get().free(mBufferHandle);
+                    if (status != android::OK) {
+                        ALOGE("SensorsAidlTestSharedMemory Gralloc failed to free buffer. Status: "
+                              "%s",
+                              android::statusToString(status).c_str());
+                    }
+                    mBufferHandle = nullptr;
+                    mBuffer = nullptr;
                     mSize = 0;
                 }
                 break;
             }
             default: {
-                if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) {
+                if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr ||
+                    mBufferHandle != nullptr) {
                     ALOGE("SensorsAidlTestSharedMemory %p not properly destructed: "
-                          "type %d, native handle %p, size %zu, buffer %p",
-                          this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer);
+                          "type %d, native handle %p, size %zu, buffer %p, buffer handle %p",
+                          this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer,
+                          mBufferHandle);
                 }
                 break;
             }
@@ -185,14 +210,33 @@
                 break;
             }
             case ISensors::SharedMemInfo::SharedMemType::GRALLOC: {
-                mGrallocWrapper = std::make_unique<::android::GrallocWrapper>();
-                if (!mGrallocWrapper->isInitialized()) {
+                static constexpr uint64_t kBufferUsage =
+                        static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA) |
+                        static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN) |
+                        static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY);
+
+                uint32_t stride = 0;
+                buffer_handle_t bufferHandle;
+                android::status_t status = android::GraphicBufferAllocator::get().allocate(
+                        size, 1, static_cast<int>(PixelFormat::BLOB), 1, kBufferUsage,
+                        &bufferHandle, &stride, "SensorVts");
+                if (status != android::OK) {
+                    ALOGE("SensorsAidlTestSharedMemory failed to allocate memory. Status: %s",
+                          android::statusToString(status).c_str());
                     break;
                 }
-
-                std::pair<native_handle_t*, void*> buf = mGrallocWrapper->allocate(size);
-                handle = buf.first;
-                buffer = static_cast<char*>(buf.second);
+                // Per the HAL, all-zeros Rect means the entire buffer
+                android::Rect rect = {0, 0, 0, 0};
+                void* ret;
+                status = android::GraphicBufferMapper::get().lock(bufferHandle, kBufferUsage, rect,
+                                                                  &ret);
+                if (status != android::OK) {
+                    ALOGE("SensorsAidlTestSharedMemory failed to import buffer: Status: %s",
+                          android::statusToString(status).c_str());
+                } else {
+                    buffer = static_cast<char*>(ret);
+                    mBufferHandle = bufferHandle;
+                }
                 break;
             }
             default:
@@ -208,9 +252,9 @@
 
     ISensors::SharedMemInfo::SharedMemType mType;
     native_handle_t* mNativeHandle;
+    buffer_handle_t mBufferHandle;
     size_t mSize;
     char* mBuffer;
-    std::unique_ptr<::android::GrallocWrapper> mGrallocWrapper;
 
     DISALLOW_COPY_AND_ASSIGN(SensorsAidlTestSharedMemory);
 };
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index b381580..becc93c 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -52,8 +52,6 @@
 using ::android::hardware::sensors::V1_0::Vec3;
 using ::android::hardware::sensors::V2_1::implementation::convertToOldSensorInfos;
 using std::chrono::duration_cast;
-using std::chrono::microseconds;
-using std::chrono::milliseconds;
 using std::chrono::nanoseconds;
 
 using EventV1_0 = ::android::hardware::sensors::V1_0::Event;
@@ -91,7 +89,7 @@
     }
 
     void waitForFlushEvents(const std::vector<SensorInfoType>& sensorsToWaitFor,
-                            int32_t numCallsToFlush, milliseconds timeout) {
+                            int32_t numCallsToFlush, std::chrono::milliseconds timeout) {
         std::unique_lock<std::recursive_mutex> lock(mFlushMutex);
         mFlushCV.wait_for(lock, timeout,
                           [&] { return flushesReceived(sensorsToWaitFor, numCallsToFlush); });
@@ -102,7 +100,8 @@
         return mEventMap[sensorHandle];
     }
 
-    void waitForEvents(const std::vector<SensorInfoType>& sensorsToWaitFor, milliseconds timeout) {
+    void waitForEvents(const std::vector<SensorInfoType>& sensorsToWaitFor,
+                       std::chrono::milliseconds timeout) {
         std::unique_lock<std::recursive_mutex> lock(mEventMutex);
         mEventCV.wait_for(lock, timeout, [&] { return eventsReceived(sensorsToWaitFor); });
     }
@@ -472,7 +471,7 @@
     }
 
     // Wait for events to be written back to the Event FMQ
-    callback.waitForEvents(sensors, milliseconds(1000) /* timeout */);
+    callback.waitForEvents(sensors, std::chrono::milliseconds(1000) /* timeout */);
     getEnvironment()->unregisterCallback();
 
     for (const auto& s : sensors) {
@@ -623,7 +622,7 @@
     }
 
     // Wait up to one second for the flush events
-    callback.waitForFlushEvents(sensors, flushCalls, milliseconds(1000) /* timeout */);
+    callback.waitForFlushEvents(sensors, flushCalls, std::chrono::milliseconds(1000) /* timeout */);
 
     // Deactivate all sensors after waiting for flush events so pending flush events are not
     // abandoned by the HAL.
@@ -748,8 +747,8 @@
 }
 
 TEST_P(SensorsHidlTest, NoStaleEvents) {
-    constexpr milliseconds kFiveHundredMs(500);
-    constexpr milliseconds kOneSecond(1000);
+    constexpr std::chrono::milliseconds kFiveHundredMs(500);
+    constexpr std::chrono::milliseconds kOneSecond(1000);
 
     // Register the callback to receive sensor events
     EventCallback callback;
@@ -757,10 +756,11 @@
 
     // This test is not valid for one-shot, on-change or special-report-mode sensors
     const std::vector<SensorInfoType> sensors = getNonOneShotAndNonOnChangeAndNonSpecialSensors();
-    milliseconds maxMinDelay(0);
+    std::chrono::milliseconds maxMinDelay(0);
     for (const SensorInfoType& sensor : sensors) {
-        milliseconds minDelay = duration_cast<milliseconds>(microseconds(sensor.minDelay));
-        maxMinDelay = milliseconds(std::max(maxMinDelay.count(), minDelay.count()));
+        std::chrono::milliseconds minDelay = duration_cast<std::chrono::milliseconds>(
+                std::chrono::microseconds(sensor.minDelay));
+        maxMinDelay = std::chrono::milliseconds(std::max(maxMinDelay.count(), minDelay.count()));
     }
 
     // Activate the sensors so that they start generating events
@@ -787,7 +787,7 @@
     }
 
     // Allow some time to pass, reset the callback, then reactivate the sensors
-    usleep(duration_cast<microseconds>(kOneSecond + (5 * maxMinDelay)).count());
+    usleep(duration_cast<std::chrono::microseconds>(kOneSecond + (5 * maxMinDelay)).count());
     callback.reset();
     activateAllSensors(true);
     callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay));
@@ -815,9 +815,10 @@
         // Ensure that the first event received is not stale by ensuring that its timestamp is
         // sufficiently different from the previous event
         const EventType newEvent = events.front();
-        milliseconds delta = duration_cast<milliseconds>(
+        std::chrono::milliseconds delta = duration_cast<std::chrono::milliseconds>(
                 nanoseconds(newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle]));
-        milliseconds sensorMinDelay = duration_cast<milliseconds>(microseconds(sensor.minDelay));
+        std::chrono::milliseconds sensorMinDelay = duration_cast<std::chrono::milliseconds>(
+                std::chrono::microseconds(sensor.minDelay));
         ASSERT_GE(delta, kFiveHundredMs + (3 * sensorMinDelay));
     }
 }
diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp
index b35280a..ab3984c 100644
--- a/sensors/common/vts/utils/Android.bp
+++ b/sensors/common/vts/utils/Android.bp
@@ -35,6 +35,7 @@
         "libbinder_ndk",
         "libutils",
         "libvndksupport",
+        "libui",
     ],
     static_libs: [
         "libaidlcommonsupport",
@@ -50,9 +51,6 @@
         "android.hardware.graphics.common-ndk_shared",
     ],
     cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
-    srcs: [
-        "GrallocWrapper.cpp",
-    ],
     export_include_dirs: [
         "include",
     ],
@@ -64,6 +62,7 @@
         "libbinder_ndk",
         "libutils",
         "libvndksupport",
+        "libui",
     ],
     static_libs: [
         "android.hardware.sensors@1.0",
@@ -71,13 +70,4 @@
         "android.hardware.sensors@2.1",
         "libaidlcommonsupport",
     ],
-    whole_static_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.allocator@4.0",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@2.1",
-        "android.hardware.graphics.mapper@3.0",
-        "android.hardware.graphics.mapper@4.0",
-    ],
 }
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
deleted file mode 100644
index a15e7fe..0000000
--- a/sensors/common/vts/utils/GrallocWrapper.cpp
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * 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 "GrallocWrapper.h"
-
-#include <aidl/android/hardware/graphics/allocator/IAllocator.h>
-#include <aidlcommonsupport/NativeHandle.h>
-#include <android/binder_manager.h>
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
-#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/2.1/IMapper.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-#include <android/hardware/graphics/mapper/4.0/IMapper.h>
-
-#include <utils/Log.h>
-
-#include <cinttypes>
-#include <memory>
-#include <type_traits>
-
-using IAllocatorAidl = ::aidl::android::hardware::graphics::allocator::IAllocator;
-using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
-using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
-using IAllocator4 = ::android::hardware::graphics::allocator::V4_0::IAllocator;
-using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
-using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
-using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
-using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
-
-using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
-using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
-using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
-
-using ::aidl::android::hardware::common::NativeHandle;
-using ::aidl::android::hardware::graphics::allocator::AllocationResult;
-
-using ::android::hardware::graphics::common::V1_0::BufferUsage;
-using ::android::hardware::graphics::common::V1_0::PixelFormat;
-
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-
-namespace android {
-
-// Since we use the same APIs across allocator/mapper HALs but they have major
-// version differences (meaning they are not related through inheritance), we
-// create a common interface abstraction for the IAllocator + IMapper combination
-// (major versions need to match in the current HALs, e.g. IAllocator 3.0 needs to
-// be paired with IMapper 3.0, so these are tied together)
-class IGrallocHalWrapper {
-  public:
-    virtual ~IGrallocHalWrapper() = default;
-
-    // IAllocator
-    virtual native_handle_t* allocate(uint32_t size) = 0;
-    virtual void freeBuffer(native_handle_t* bufferHandle) = 0;
-
-    // IMapper
-    virtual void* lock(native_handle_t* bufferHandle) = 0;
-    virtual void unlock(native_handle_t* bufferHandle) = 0;
-};
-
-namespace {
-
-bool failed(Error2 error) {
-    return (error != Error2::NONE);
-}
-bool failed(Error3 error) {
-    return (error != Error3::NONE);
-}
-bool failed(Error4 error) {
-    return (error != Error4::NONE);
-}
-
-template <typename>
-struct FirstArg;
-
-// Template specialization for pointer to a non-static member function, which exposes
-// the type of the first argument given to said function
-template <typename ReturnType, typename ClassT, typename Arg1, typename... OtherArgs>
-struct FirstArg<ReturnType (ClassT::*)(Arg1, OtherArgs...)> {
-    using type = Arg1;
-};
-
-// Alias to FirstArg which also removes any reference type and const associated
-template <typename T>
-using BaseTypeOfFirstArg = typename std::remove_const<
-        typename std::remove_reference<typename FirstArg<T>::type>::type>::type;
-
-// Since all the type and function names are the same for the things we use across the major HAL
-// versions, we use template magic to avoid repeating ourselves.
-template <typename AllocatorT, typename MapperT,
-          template <typename> typename AllocatorWrapperT = sp>
-class GrallocHalWrapper : public IGrallocHalWrapper {
-  public:
-    GrallocHalWrapper(const AllocatorWrapperT<AllocatorT>& allocator, const sp<MapperT>& mapper)
-        : mAllocator(allocator), mMapper(mapper) {
-        if (mapper->isRemote()) {
-            ALOGE("Mapper is in passthrough mode");
-        }
-    }
-
-    virtual native_handle_t* allocate(uint32_t size) override;
-    virtual void freeBuffer(native_handle_t* bufferHandle) override;
-
-    virtual void* lock(native_handle_t* bufferHandle) override;
-    virtual void unlock(native_handle_t* bufferHandle) override;
-
-  private:
-    static constexpr uint64_t kBufferUsage =
-            static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN |
-                                  BufferUsage::CPU_WRITE_RARELY);
-    AllocatorWrapperT<AllocatorT> mAllocator;
-    sp<MapperT> mMapper;
-
-    // v2.0 and v3.0 use vec<uint32_t> for BufferDescriptor, but v4.0 uses vec<uint8_t>, so use
-    // some template magic to deduce the right type based off of the first argument to allocate(),
-    // which is always the version-specific BufferDescriptor type
-    typedef BaseTypeOfFirstArg<decltype(&AllocatorT::allocate)> BufferDescriptorT;
-
-    BufferDescriptorT getDescriptor(uint32_t size);
-    native_handle_t* importBuffer(const hidl_handle& rawHandle);
-};
-
-template <>
-native_handle_t* GrallocHalWrapper<IAllocatorAidl, IMapper4, std::shared_ptr>::allocate(
-        uint32_t size) {
-    constexpr uint32_t kBufferCount = 1;
-    BufferDescriptorT descriptor = getDescriptor(size);
-    native_handle_t* bufferHandle = nullptr;
-
-    AllocationResult result;
-    auto status = mAllocator->allocate(descriptor, kBufferCount, &result);
-    if (!status.isOk()) {
-        status_t error = status.getExceptionCode();
-        ALOGE("Failed to allocate buffer: %" PRId32, static_cast<int32_t>(error));
-    } else if (result.buffers.size() != kBufferCount) {
-        ALOGE("Invalid buffer array size (got %zu, expected %" PRIu32 ")", result.buffers.size(),
-              kBufferCount);
-    } else {
-        // Convert from AIDL NativeHandle to native_handle_t to hidl_handle
-        hidl_handle hidlHandle;
-        hidlHandle.setTo(dupFromAidl(result.buffers[0]), /*shouldOwn*/ true);
-        bufferHandle = importBuffer(hidlHandle);
-    }
-
-    return bufferHandle;
-}
-
-template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
-native_handle_t* GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::allocate(
-        uint32_t size) {
-    constexpr uint32_t kBufferCount = 1;
-    BufferDescriptorT descriptor = getDescriptor(size);
-    native_handle_t* bufferHandle = nullptr;
-
-    auto callback = [&](auto error, uint32_t /*stride*/, const hidl_vec<hidl_handle>& buffers) {
-        if (failed(error)) {
-            ALOGE("Failed to allocate buffer: %" PRId32, static_cast<int32_t>(error));
-        } else if (buffers.size() != kBufferCount) {
-            ALOGE("Invalid buffer array size (got %zu, expected %" PRIu32 ")", buffers.size(),
-                  kBufferCount);
-        } else {
-            bufferHandle = importBuffer(buffers[0]);
-        }
-    };
-
-    mAllocator->allocate(descriptor, kBufferCount, callback);
-    return bufferHandle;
-}
-
-template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
-void GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::freeBuffer(
-        native_handle_t* bufferHandle) {
-    auto error = mMapper->freeBuffer(bufferHandle);
-    if (!error.isOk() || failed(error)) {
-        ALOGE("Failed to free buffer %p", bufferHandle);
-    }
-}
-
-template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
-typename GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::BufferDescriptorT
-GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::getDescriptor(uint32_t size) {
-    typename MapperT::BufferDescriptorInfo descriptorInfo = {
-            .width = size,
-            .height = 1,
-            .layerCount = 1,
-            .format = static_cast<decltype(descriptorInfo.format)>(PixelFormat::BLOB),
-            .usage = kBufferUsage,
-    };
-
-    BufferDescriptorT descriptor;
-    auto callback = [&](auto error, const BufferDescriptorT& tmpDescriptor) {
-        if (failed(error)) {
-            ALOGE("Failed to create descriptor: %" PRId32, static_cast<int32_t>(error));
-        } else {
-            descriptor = tmpDescriptor;
-        }
-    };
-
-    mMapper->createDescriptor(descriptorInfo, callback);
-    return descriptor;
-}
-
-template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
-native_handle_t* GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::importBuffer(
-        const hidl_handle& rawHandle) {
-    native_handle_t* bufferHandle = nullptr;
-
-    mMapper->importBuffer(rawHandle, [&](auto error, void* tmpBuffer) {
-        if (failed(error)) {
-            ALOGE("Failed to import buffer %p: %" PRId32, rawHandle.getNativeHandle(),
-                  static_cast<int32_t>(error));
-        } else {
-            bufferHandle = static_cast<native_handle_t*>(tmpBuffer);
-        }
-    });
-
-    return bufferHandle;
-}
-
-template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
-void* GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::lock(
-        native_handle_t* bufferHandle) {
-    // Per the HAL, all-zeros Rect means the entire buffer
-    typename MapperT::Rect accessRegion = {};
-    hidl_handle acquireFenceHandle;  // No fence needed, already safe to lock
-
-    void* data = nullptr;
-    mMapper->lock(bufferHandle, kBufferUsage, accessRegion, acquireFenceHandle,
-                  [&](auto error, void* tmpData, ...) {  // V3/4 pass extra args we don't use
-                      if (failed(error)) {
-                          ALOGE("Failed to lock buffer %p: %" PRId32, bufferHandle,
-                                static_cast<int32_t>(error));
-                      } else {
-                          data = tmpData;
-                      }
-                  });
-
-    return data;
-}
-
-template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
-void GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::unlock(
-        native_handle_t* bufferHandle) {
-    mMapper->unlock(bufferHandle, [&](auto error, const hidl_handle& /*releaseFence*/) {
-        if (failed(error)) {
-            ALOGE("Failed to unlock buffer %p: %" PRId32, bufferHandle,
-                  static_cast<int32_t>(error));
-        }
-    });
-}
-
-}  // anonymous namespace
-
-GrallocWrapper::GrallocWrapper() {
-    sp<IAllocator4> allocator4 = IAllocator4::getService();
-    sp<IMapper4> mapper4 = IMapper4::getService();
-
-    const auto kAllocatorSvc = std::string(IAllocatorAidl::descriptor) + "/default";
-    std::shared_ptr<IAllocatorAidl> allocatorAidl;
-    if (AServiceManager_isDeclared(kAllocatorSvc.c_str())) {
-        allocatorAidl = IAllocatorAidl::fromBinder(
-                ndk::SpAIBinder(AServiceManager_checkService(kAllocatorSvc.c_str())));
-    }
-
-    // As of T, AIDL Allocator is supported only with HIDL Mapper4
-    // (ref: VtsHalGraphicsAllocatorAidl_TargetTest.cpp)
-    if (allocatorAidl != nullptr && mapper4 != nullptr) {
-        ALOGD("Using AIDL IAllocator + HIDL IMapper v4.0");
-        mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
-                new GrallocHalWrapper<IAllocatorAidl, IMapper4, std::shared_ptr>(allocatorAidl,
-                                                                                 mapper4));
-    } else if (allocator4 != nullptr && mapper4 != nullptr) {
-        ALOGD("AIDL IAllocator not found, using HIDL IAllocator/IMapper v4.0");
-        mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
-                new GrallocHalWrapper<IAllocator4, IMapper4>(allocator4, mapper4));
-    } else {
-        ALOGD("Graphics HALs 4.0 not found (allocator %d mapper %d), falling back to 3.0",
-              (allocator4 != nullptr), (mapper4 != nullptr));
-
-        sp<IAllocator3> allocator3 = IAllocator3::getService();
-        sp<IMapper3> mapper3 = IMapper3::getService();
-
-        if (allocator3 != nullptr && mapper3 != nullptr) {
-            mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
-                    new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
-        } else {
-            ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x",
-                  (allocator3 != nullptr), (mapper3 != nullptr));
-
-            sp<IAllocator2> allocator2 = IAllocator2::getService();
-            sp<IMapper2> mapper2 = IMapper2_1::getService();
-            if (mapper2 == nullptr) {
-                mapper2 = IMapper2::getService();
-            }
-
-            if (allocator2 != nullptr && mapper2 != nullptr) {
-                mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
-                        new GrallocHalWrapper<IAllocator2, IMapper2>(allocator2, mapper2));
-            } else {
-                ALOGE("Couldn't open graphics HALs (2.x allocator %d mapper %d)",
-                      (allocator2 != nullptr), (mapper2 != nullptr));
-            }
-        }
-    }
-}
-
-GrallocWrapper::~GrallocWrapper() {
-    for (auto bufferHandle : mAllocatedBuffers) {
-        mGrallocHal->unlock(bufferHandle);
-        mGrallocHal->freeBuffer(bufferHandle);
-    }
-    mAllocatedBuffers.clear();
-}
-
-std::pair<native_handle_t*, void*> GrallocWrapper::allocate(uint32_t size) {
-    native_handle_t* bufferHandle = mGrallocHal->allocate(size);
-    void* buffer = nullptr;
-    if (bufferHandle) {
-        buffer = mGrallocHal->lock(bufferHandle);
-        if (buffer) {
-            mAllocatedBuffers.insert(bufferHandle);
-        } else {
-            mGrallocHal->freeBuffer(bufferHandle);
-            bufferHandle = nullptr;
-        }
-    }
-    return std::make_pair<>(bufferHandle, buffer);
-}
-
-void GrallocWrapper::freeBuffer(native_handle_t* bufferHandle) {
-    if (mAllocatedBuffers.erase(bufferHandle)) {
-        mGrallocHal->unlock(bufferHandle);
-        mGrallocHal->freeBuffer(bufferHandle);
-    }
-}
-
-}  // namespace android
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
deleted file mode 100644
index ebbcb2c..0000000
--- a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * 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 <utils/NativeHandle.h>
-
-#include <memory>
-#include <string>
-#include <unordered_set>
-#include <utility>
-
-namespace android {
-
-class IGrallocHalWrapper;
-
-// Reference: hardware/interfaces/graphics/mapper/2.0/vts/functional/
-class GrallocWrapper {
-   public:
-    GrallocWrapper();
-    ~GrallocWrapper();
-
-    // After constructing this object, this function must be called to check the result. If it
-    // returns false, other methods are not safe to call.
-    bool isInitialized() const { return (mGrallocHal != nullptr); };
-
-    // Allocates a gralloc buffer suitable for direct channel sensors usage with the given size.
-    // The buffer should be freed using freeBuffer when it's not needed anymore; otherwise it'll
-    // be freed when this object is destroyed.
-    // Returns a handle to the buffer, and a CPU-accessible pointer for reading. On failure, both
-    // will be set to nullptr.
-    std::pair<native_handle_t*, void*> allocate(uint32_t size);
-
-    // Releases a gralloc buffer previously returned by allocate()
-    void freeBuffer(native_handle_t* bufferHandle);
-
-  private:
-    std::unique_ptr<IGrallocHalWrapper> mGrallocHal;
-
-    // Keep track of all cloned and imported handles.  When a test fails with
-    // ASSERT_*, the destructor will free the handles for the test.
-    std::unordered_set<native_handle_t*> mAllocatedBuffers;
-};
-
-}  // namespace android
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
index 39084a4..b96adb3 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
@@ -17,7 +17,11 @@
 #ifndef ANDROID_SENSORS_TEST_SHARED_MEMORY_H
 #define ANDROID_SENSORS_TEST_SHARED_MEMORY_H
 
-#include "GrallocWrapper.h"
+#include <aidl/android/hardware/graphics/common/BufferUsage.h>
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBufferMapper.h>
 
 #include <android-base/macros.h>
 #include <log/log.h>
@@ -28,6 +32,8 @@
 #include <cutils/ashmem.h>
 
 using namespace ::android::hardware::sensors::V1_0;
+using ::aidl::android::hardware::graphics::common::BufferUsage;
+using ::aidl::android::hardware::graphics::common::PixelFormat;
 
 template <class SensorTypeVersion, class EventType>
 class SensorsTestSharedMemory {
@@ -48,11 +54,20 @@
     }
 
     SharedMemInfo getSharedMemInfo() const {
-        SharedMemInfo mem = {.type = mType,
-                             .format = SharedMemFormat::SENSORS_EVENT,
-                             .size = static_cast<uint32_t>(mSize),
-                             .memoryHandle = mNativeHandle};
-        return mem;
+        if (mType == SharedMemType::GRALLOC) {
+            SharedMemInfo mem = {.type = mType,
+                                 .format = SharedMemFormat::SENSORS_EVENT,
+                                 .size = static_cast<uint32_t>(mSize),
+                                 .memoryHandle = mBufferHandle};
+            return mem;
+
+        } else {
+            SharedMemInfo mem = {.type = mType,
+                                 .format = SharedMemFormat::SENSORS_EVENT,
+                                 .size = static_cast<uint32_t>(mSize),
+                                 .memoryHandle = mNativeHandle};
+            return mem;
+        }
     }
     char* getBuffer() const { return mBuffer; }
     size_t getSize() const { return mSize; }
@@ -128,17 +143,26 @@
             }
             case SharedMemType::GRALLOC: {
                 if (mSize != 0) {
-                    mGrallocWrapper->freeBuffer(mNativeHandle);
-                    mNativeHandle = nullptr;
+                    android::status_t status =
+                            android::GraphicBufferAllocator::get().free(mBufferHandle);
+                    if (status != android::OK) {
+                        ALOGE("SensorsAidlTestSharedMemory Gralloc failed to free buffer. Status: "
+                              "%s",
+                              android::statusToString(status).c_str());
+                    }
+                    mBufferHandle = nullptr;
+                    mBuffer = nullptr;
                     mSize = 0;
                 }
                 break;
             }
             default: {
-                if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) {
-                    ALOGE("SensorsTestSharedMemory %p not properly destructed: "
-                          "type %d, native handle %p, size %zu, buffer %p",
-                          this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer);
+                if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr ||
+                    mBufferHandle != nullptr) {
+                    ALOGE("SensorsAidlTestSharedMemory %p not properly destructed: "
+                          "type %d, native handle %p, size %zu, buffer %p, buffer handle %p",
+                          this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer,
+                          mBufferHandle);
                 }
                 break;
             }
@@ -171,14 +195,33 @@
                 break;
             }
             case SharedMemType::GRALLOC: {
-                mGrallocWrapper = std::make_unique<::android::GrallocWrapper>();
-                if (!mGrallocWrapper->isInitialized()) {
+                static constexpr uint64_t kBufferUsage =
+                        static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA) |
+                        static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN) |
+                        static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY);
+
+                uint32_t stride = 0;
+                buffer_handle_t bufferHandle;
+                android::status_t status = android::GraphicBufferAllocator::get().allocate(
+                        size, 1, static_cast<int>(PixelFormat::BLOB), 1, kBufferUsage,
+                        &bufferHandle, &stride, "SensorVts");
+                if (status != android::OK) {
+                    ALOGE("SensorsAidlTestSharedMemory failed to allocate memory. Status: %s",
+                          android::statusToString(status).c_str());
                     break;
                 }
-
-                std::pair<native_handle_t*, void*> buf = mGrallocWrapper->allocate(size);
-                handle = buf.first;
-                buffer = static_cast<char*>(buf.second);
+                // Per the HAL, all-zeros Rect means the entire buffer
+                android::Rect rect = {0, 0, 0, 0};
+                void* ret;
+                status = android::GraphicBufferMapper::get().lock(bufferHandle, kBufferUsage, rect,
+                                                                  &ret);
+                if (status != android::OK) {
+                    ALOGE("SensorsAidlTestSharedMemory failed to import buffer: Status: %s",
+                          android::statusToString(status).c_str());
+                } else {
+                    buffer = static_cast<char*>(ret);
+                    mBufferHandle = bufferHandle;
+                }
                 break;
             }
             default:
@@ -194,9 +237,9 @@
 
     SharedMemType mType;
     native_handle_t* mNativeHandle;
+    buffer_handle_t mBufferHandle;
     size_t mSize;
     char* mBuffer;
-    std::unique_ptr<::android::GrallocWrapper> mGrallocWrapper;
 
     DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
 };
diff --git a/soundtrigger/aidl/Android.bp b/soundtrigger/aidl/Android.bp
index 27d43d3..aa400c1 100644
--- a/soundtrigger/aidl/Android.bp
+++ b/soundtrigger/aidl/Android.bp
@@ -22,8 +22,8 @@
         "android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl",
     ],
     stability: "vintf",
-    imports: [
-        "android.media.soundtrigger.types-V1",
+    defaults: [
+        "latest_android_media_soundtrigger_types_import_interface",
     ],
     backend: {
         cpp: {
@@ -34,6 +34,7 @@
             sdk_version: "module_current",
         },
     },
+    frozen: false,
     versions_with_info: [
         {
             version: "1",
@@ -45,7 +46,7 @@
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_soundtrigger3 = "android.hardware.soundtrigger3-V1"
+latest_android_hardware_soundtrigger3 = "android.hardware.soundtrigger3-V2"
 
 // Modules that depend on android.hardware.soundtrigger3 directly can include
 // the following java_defaults to avoid explicitly managing dependency versions
@@ -56,3 +57,10 @@
         latest_android_hardware_soundtrigger3 + "-java",
     ],
 }
+
+cc_defaults {
+    name: "latest_android_hardware_soundtrigger3_ndk_shared",
+    shared_libs: [
+        latest_android_hardware_soundtrigger3 + "-ndk",
+    ],
+}
diff --git a/tv/input/aidl/Android.bp b/tv/input/aidl/Android.bp
index 35f510a..cd69130 100644
--- a/tv/input/aidl/Android.bp
+++ b/tv/input/aidl/Android.bp
@@ -35,6 +35,5 @@
             ],
         },
     ],
-    frozen: true,
-
+    frozen: false,
 }
diff --git a/tv/input/aidl/aidl_api/android.hardware.tv.input/current/android/hardware/tv/input/TvMessageEvent.aidl b/tv/input/aidl/aidl_api/android.hardware.tv.input/current/android/hardware/tv/input/TvMessageEvent.aidl
index 94fe665..3c1cb74 100644
--- a/tv/input/aidl/aidl_api/android.hardware.tv.input/current/android/hardware/tv/input/TvMessageEvent.aidl
+++ b/tv/input/aidl/aidl_api/android.hardware.tv.input/current/android/hardware/tv/input/TvMessageEvent.aidl
@@ -37,4 +37,5 @@
   android.hardware.tv.input.TvMessageEventType type;
   int streamId;
   android.hardware.tv.input.TvMessage[] messages;
+  int deviceId;
 }
diff --git a/tv/input/aidl/android/hardware/tv/input/ITvInputCallback.aidl b/tv/input/aidl/android/hardware/tv/input/ITvInputCallback.aidl
index a3afd41..4121fc7 100644
--- a/tv/input/aidl/android/hardware/tv/input/ITvInputCallback.aidl
+++ b/tv/input/aidl/android/hardware/tv/input/ITvInputCallback.aidl
@@ -32,17 +32,20 @@
      * Notifies the client that an TV message event has occurred. For possible event types,
      * check {@link android.hardware.tv.input.TvMessageEventType}.
      *
-     * The first message in a list of messages contained in a
+     * <p> For implementations of version 1, The first message in a list of messages contained in a
      * {@link android.hardware.tv.input.TvMessageEvent} should always have a
      * {@link android.hardware.tv.input.TvMessage#subType} of "device_id",
      * otherwise the event is discarded. When the subType of a message is "device_id", the ID of
      * the device that sent the message should be contained in
-     * {@link android.hardware.tv.input.TvMessage#groupId}
+     * {@link android.hardware.tv.input.TvMessage#groupId}.
      *
-     * Invoking this callback for the first time immediately triggers
+     * <p> For version 2 and beyond, the device ID should be contained in
+     * {@link android.hardware.tv.input.TvMessageEvent#deviceId}.
+     *
+     * <p> Invoking this callback for the first time immediately triggers
      * {@link android.hardware.tv.input.ITvInput#getTvMessageQueueDesc}. It is
-     * expected for the queue to be ready with
-     * the relevant messages for the event before this callback is called.
+     * expected for the queue to be ready with the relevant messages for the event before this
+     * callback is called.
      *
      * @param event Event passed to the client.
      */
diff --git a/tv/input/aidl/android/hardware/tv/input/TvMessageEvent.aidl b/tv/input/aidl/android/hardware/tv/input/TvMessageEvent.aidl
index 74a078a..e04a725 100644
--- a/tv/input/aidl/android/hardware/tv/input/TvMessageEvent.aidl
+++ b/tv/input/aidl/android/hardware/tv/input/TvMessageEvent.aidl
@@ -25,4 +25,5 @@
 
     int streamId;
     TvMessage[] messages;
+    int deviceId;
 }
diff --git a/tv/input/aidl/default/TvInput.cpp b/tv/input/aidl/default/TvInput.cpp
index 2ee8bcf..f6a64c4 100644
--- a/tv/input/aidl/default/TvInput.cpp
+++ b/tv/input/aidl/default/TvInput.cpp
@@ -43,6 +43,9 @@
                                       new TvStreamConfigWrapper(11, 360, 480, false))}};
     mStreamConfigs[3] = {{5, shared_ptr<TvStreamConfigWrapper>(
                                      new TvStreamConfigWrapper(5, 1080, 1920, false))}};
+
+    mQueue = shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>>(
+            new (std::nothrow) AidlMessageQueue<int8_t, SynchronizedReadWrite>(8));
 }
 
 ::ndk::ScopedAStatus TvInput::setCallback(const shared_ptr<ITvInputCallback>& in_callback) {
@@ -74,7 +77,9 @@
         return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
     }
 
+    // When calling notifyTvMessage, make sure to verify against this map.
     mTvMessageEventEnabled[deviceId][streamId][in_type] = enabled;
+
     return ::ndk::ScopedAStatus::ok();
 }
 
@@ -82,11 +87,17 @@
         MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue, int32_t in_deviceId,
         int32_t in_streamId) {
     ALOGV("%s", __FUNCTION__);
+    ::ndk::ScopedAStatus status = ::ndk::ScopedAStatus::ok();
     if (mStreamConfigs.count(in_deviceId) == 0) {
         ALOGW("Device with id %d isn't available", in_deviceId);
-        return ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
+        status = ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS);
+    } else if (!mQueue->isValid()) {
+        ALOGE("Tv Message Queue was not properly initialized");
+        status = ::ndk::ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_STATE);
+    } else {
+        *out_queue = mQueue->dupeDesc();
     }
-    return ::ndk::ScopedAStatus::ok();
+    return status;
 }
 
 ::ndk::ScopedAStatus TvInput::getStreamConfigurations(int32_t in_deviceId,
diff --git a/tv/input/aidl/default/TvInput.h b/tv/input/aidl/default/TvInput.h
index 5776961..595f017 100644
--- a/tv/input/aidl/default/TvInput.h
+++ b/tv/input/aidl/default/TvInput.h
@@ -66,6 +66,7 @@
     map<int32_t, shared_ptr<TvInputDeviceInfoWrapper>> mDeviceInfos;
     map<int32_t, map<int32_t, shared_ptr<TvStreamConfigWrapper>>> mStreamConfigs;
     TvMessageEnabledMap mTvMessageEventEnabled;
+    shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>> mQueue;
 };
 
 }  // namespace input
diff --git a/tv/input/aidl/vts/functional/Android.bp b/tv/input/aidl/vts/functional/Android.bp
index 22487ea..930c5a8 100644
--- a/tv/input/aidl/vts/functional/Android.bp
+++ b/tv/input/aidl/vts/functional/Android.bp
@@ -32,7 +32,7 @@
         "libvndksupport",
         "libfmq",
         "android.hardware.common.fmq-V1-ndk",
-        "android.hardware.tv.input-V1-ndk",
+        "android.hardware.tv.input-V2-ndk",
     ],
     require_root: true,
 }
diff --git a/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.cpp b/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.cpp
index 8d3395b..746ae1e 100644
--- a/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.cpp
+++ b/tv/input/aidl/vts/functional/VtsHalTvInputTargetTest.cpp
@@ -355,8 +355,12 @@
     }
     int32_t stream_id = streamConfigs[0].streamId;
     ALOGD("GetTvMessageQueueTest: device_id=%d, stream_id=%d", device_id, stream_id);
-    MQDescriptor<int8_t, SynchronizedReadWrite> queue;
-    tv_input_->getTvMessageQueueDesc(&queue, device_id, stream_id);
+    MQDescriptor<int8_t, SynchronizedReadWrite> queueDescriptor;
+    AidlMessageQueue<int8_t, SynchronizedReadWrite>* queue;
+    tv_input_->getTvMessageQueueDesc(&queueDescriptor, device_id, stream_id);
+    queue = new (std::nothrow) AidlMessageQueue<int8_t, SynchronizedReadWrite>(queueDescriptor);
+    ASSERT_TRUE(queue->isValid());
+    delete queue;
 }
 
 INSTANTIATE_TEST_SUITE_P(PerInstance, TvInputAidlTest,
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-----
-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
------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/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl b/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl
index 58777c5..4bedce0 100644
--- a/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl
+++ b/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl
@@ -73,8 +73,9 @@
     /**
      * Arbitrary information communicated in discovery packets - there is no semantic meaning to
      * these bytes. They are passed-through from publisher to subscriber as-is with no parsing. Max
-     * length: |NanCapabilities.maxExtendedServiceSpecificInfoLen|. Spec: Service Descriptor
-     * Extension Attribute (SDEA) / Service Info
+     * length: |NanCapabilities.maxExtendedServiceSpecificInfoLen|. This info is using Generic
+     * Service Protocol with setting Service Info type to 2 (Generic). NAN Spec: Service
+     * Descriptor Extension Attribute (SDEA) / Service Info
      */
     byte[] extendedServiceSpecificInfo;
     /**
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-----