Don't send OID and size in NFA_SendVsCommand() am: b012c34771

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/3450954

Change-Id: Ie8ba3f0d88395e0eb038aeaf8450a480fecb3042
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/METADATA b/METADATA
deleted file mode 100644
index d97975c..0000000
--- a/METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-third_party {
-  license_type: NOTICE
-}
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index de7aa35..8c53006 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -5,6 +5,7 @@
 bpfmt = true
 clang_format = true
 aidl_format = true
+gofmt = true
 
 [Hook Scripts]
 aosp_hook_confirmationui = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} confirmationui
diff --git a/atrace/1.0/vts/functional/Android.bp b/atrace/1.0/vts/functional/Android.bp
index 9681aa2..16fbaa2 100644
--- a/atrace/1.0/vts/functional/Android.bp
+++ b/atrace/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/audio/OWNERS b/audio/OWNERS
index 3671685..80e2765 100644
--- a/audio/OWNERS
+++ b/audio/OWNERS
@@ -2,3 +2,4 @@
 
 elaurent@google.com
 mnaganov@google.com
+yaoshunkai@google.com
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 4902497..97577d1 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -60,7 +60,7 @@
         ndk: {
             apex_available: [
                 "//apex_available:platform",
-                "com.android.btservices",
+                "com.android.bt",
             ],
             min_sdk_version: "31",
         },
@@ -228,6 +228,13 @@
     ],
 }
 
+rust_defaults {
+    name: "latest_android_hardware_audio_core_rust",
+    rustlibs: [
+        latest_android_hardware_audio_core + "-rust",
+    ],
+}
+
 // Used for the standalone sounddose HAL
 aidl_interface {
     name: "android.hardware.audio.core.sounddose",
@@ -303,6 +310,7 @@
         "android.hardware.audio_defaults",
         "latest_android_hardware_audio_common_import_interface",
         "latest_android_media_audio_common_types_import_interface",
+        "latest_android_media_audio_eraser_types_import_interface",
     ],
     srcs: [
         "android/hardware/audio/effect/AcousticEchoCanceler.aidl",
@@ -317,6 +325,7 @@
         "android/hardware/audio/effect/DynamicsProcessing.aidl",
         "android/hardware/audio/effect/EnvironmentalReverb.aidl",
         "android/hardware/audio/effect/Equalizer.aidl",
+        "android/hardware/audio/effect/Eraser.aidl",
         "android/hardware/audio/effect/Flags.aidl",
         "android/hardware/audio/effect/HapticGenerator.aidl",
         "android/hardware/audio/effect/IEffect.aidl",
diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING
index e325001..26f4b3a 100644
--- a/audio/aidl/TEST_MAPPING
+++ b/audio/aidl/TEST_MAPPING
@@ -72,12 +72,7 @@
       "name": "audiosystem_tests"
     },
     {
-      "name": "CtsVirtualDevicesTestCases",
-      "options" : [
-        {
-          "include-filter": "android.virtualdevice.cts.VirtualAudioTest"
-        }
-      ]
+      "name": "CtsVirtualDevicesAudioTestCases"
     }
   ]
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
index 115da1d..36f22ae 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
@@ -44,6 +44,7 @@
   const String EFFECT_TYPE_UUID_DYNAMICS_PROCESSING = "7261676f-6d75-7369-6364-28e2fd3ac39e";
   const String EFFECT_TYPE_UUID_ENV_REVERB = "c2e5d5f0-94bd-4763-9cac-4e234d06839e";
   const String EFFECT_TYPE_UUID_EQUALIZER = "0bed4300-ddd6-11db-8f34-0002a5d5c51b";
+  const String EFFECT_TYPE_UUID_ERASER = "fa81a9ac-588b-11ed-9b6a-0242ac120002";
   const String EFFECT_TYPE_UUID_HAPTIC_GENERATOR = "1411e6d6-aecd-4021-a1cf-a6aceb0d71e5";
   const String EFFECT_TYPE_UUID_LOUDNESS_ENHANCER = "fe3199be-aed0-413f-87bb-11260eb63cf1";
   const String EFFECT_TYPE_UUID_NS = "58b4b260-8e06-11e0-aa8e-0002a5d5c51b";
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Eraser.aidl
similarity index 81%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Eraser.aidl
index c1dc51c..5d8abd5 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Eraser.aidl
@@ -31,10 +31,15 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.audio.effect;
 @VintfStability
-union AcquiredInfoAndVendorCode {
-  android.hardware.biometrics.fingerprint.AcquiredInfo acquiredInfo = android.hardware.biometrics.fingerprint.AcquiredInfo.UNKNOWN;
-  int vendorCode;
+union Eraser {
+  android.hardware.audio.effect.VendorExtension vendor;
+  android.media.audio.eraser.Capability capability;
+  android.media.audio.eraser.Configuration configuration;
+  @VintfStability
+  union Id {
+    android.hardware.audio.effect.VendorExtension vendorExtensionTag;
+    android.hardware.audio.effect.Eraser.Tag commonTag;
+  }
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl
index 8addab7..aa1a86f 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl
@@ -55,6 +55,9 @@
   parcelable HapticScale {
     int id;
     android.hardware.audio.effect.HapticGenerator.VibratorScale scale = android.hardware.audio.effect.HapticGenerator.VibratorScale.MUTE;
+    float scaleFactor = (-1.0f) /* -1.000000f */;
+    float adaptiveScaleFactor = (-1.0f) /* -1.000000f */;
+    const float UNDEFINED_SCALE_FACTOR = (-1.0f) /* -1.000000f */;
   }
   @VintfStability
   parcelable VibratorInformation {
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl
index ff33c42..40a49de 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl
@@ -63,6 +63,7 @@
     android.hardware.audio.effect.Volume.Id volumeTag;
     android.hardware.audio.effect.Parameter.Tag commonTag;
     android.hardware.audio.effect.Spatializer.Id spatializerTag;
+    android.hardware.audio.effect.Eraser.Id eraserTag;
   }
   @VintfStability
   parcelable Common {
@@ -95,5 +96,6 @@
     android.hardware.audio.effect.Visualizer visualizer;
     android.hardware.audio.effect.Volume volume;
     android.hardware.audio.effect.Spatializer spatializer;
+    android.hardware.audio.effect.Eraser eraser;
   }
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl
index f6d6ee2..96d57d8 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl
@@ -40,5 +40,6 @@
   union Type {
     android.media.audio.common.AudioStreamType streamType = android.media.audio.common.AudioStreamType.INVALID;
     android.media.audio.common.AudioSource source;
+    android.media.audio.common.AudioDevice device;
   }
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl
index 17f9814..873fb43 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl
@@ -37,4 +37,5 @@
   INIT,
   IDLE,
   PROCESSING,
+  DRAINING,
 }
diff --git a/audio/aidl/android/hardware/audio/core/IStreamOut.aidl b/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
index f26dc1c..111969f 100644
--- a/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
+++ b/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
@@ -214,7 +214,8 @@
      *
      * The range of supported values for speed and pitch factors is provided by
      * the 'IModule.getSupportedPlaybackRateFactors' method. Out of range speed
-     * and pitch values must not be rejected if the fallback mode is 'MUTE'.
+     * and pitch values may result in silent playback instead of returning an
+     * error in the case when the fallback mode is 'MUTE'.
      *
      * @param playbackRate Playback parameters to set.
      * @throws EX_ILLEGAL_ARGUMENT If provided parameters are out of acceptable range.
diff --git a/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl b/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
index 65ea9ef..cfe001e 100644
--- a/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
+++ b/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
@@ -386,14 +386,23 @@
          * For input streams: the moment when data at the specified stream position
          *   was acquired (i.e. capture position).
          *
-         * The observable position must never be reset by the HAL module.
-         * The data type of the frame counter is large enough to support
-         * continuous counting for years of operation.
+         * The observable position must never be reset by the HAL module,
+         * providing an abstraction of continuous audio data flow. The data
+         * type of the frame counter is large enough to support continuous
+         * counting for years of operation.
          */
         Position observable;
         /**
          * Used only for MMap streams to provide the hardware read / write
          * position for audio data in the shared memory buffer 'audio.mmap'.
+         * Similar to the observable position, the 'Position::UNKNOWN' value
+         * can be returned when the HAL module is unable to retrieve the current
+         * position.
+         *
+         * The hardware position must never be reset by the HAL module,
+         * providing an abstraction of continuous audio data flow. The data
+         * type of the frame counter is large enough to support continuous
+         * counting for years of operation.
          */
         Position hardware;
         /**
diff --git a/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv b/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv
index 56b7926..e2da90d 100644
--- a/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv
+++ b/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv
@@ -45,6 +45,8 @@
     PAUSED -> ACTIVE [label="start"];                 // consumer -> active
     PAUSED -> IDLE [label="flush"];                   // producer -> passive, buffer is cleared
     DRAINING -> IDLE [label="←IStreamCallback.onDrainReady"];
+    DRAINING -> DRAINING [label="←IStreamCallback.onDrainReady"];  // allowed for `DRAIN_EARLY_NOTIFY`
+    DRAINING -> IDLE [label="<empty buffer>"];        // allowed for `DRAIN_EARLY_NOTIFY`
     DRAINING -> TRANSFERRING [label="burst"];         // producer -> active
     DRAINING -> ACTIVE [label="burst"];               // full write
     DRAINING -> DRAIN_PAUSED [label="pause"];         // consumer -> passive (not consuming)
diff --git a/audio/aidl/android/hardware/audio/effect/CommandId.aidl b/audio/aidl/android/hardware/audio/effect/CommandId.aidl
index d940b42..de573bf 100644
--- a/audio/aidl/android/hardware/audio/effect/CommandId.aidl
+++ b/audio/aidl/android/hardware/audio/effect/CommandId.aidl
@@ -33,25 +33,39 @@
     /**
      * Start effect engine processing.
      * An effect instance must start processing data and transfer to PROCESSING state if it is in
-     * IDLE state and have all necessary information. Otherwise it must:
-     * 1. Throw a EX_ILLEGAL_STATE exception if effect is not in IDLE state, or
-     * 2. Throw a EX_TRANSACTION_FAILED for all other errors.
+     * IDLE or DRAINING state and has all necessary information. Otherwise, it must:
+     * 1. Throw an EX_ILLEGAL_STATE exception if the effect is not in IDLE or DRAINING state, or
+     * 2. Throw an EX_TRANSACTION_FAILED for all other errors.
      *
-     * Depending on parameters set to the effect instance, effect may do process or reverse
-     * process after START command.
+     * If an effect instance in DRAINING state receives a START command, it must transit back to
+     * PROCESSING state.
      */
     START = 0,
     /**
-     * Stop effect engine processing with all resource kept.
-     * The currently processed audio data will be discarded if the effect engine is in PROCESSING
-     * state.
-     * Effect instance must do nothing and return ok when it receive STOP command in IDLE state.
+     * Stop effect engine processing with all resources kept.
+     * If the effect is in **PROCESSING** state:
+     *   - It must transition to **IDLE** state if no intermediate operations are required.
+     *   - It must transition to **DRAINING** state if draining (e.g., fading) is required.
+     *     - The instance must automatically transition to **IDLE** after draining.
+     *     - It must ignore any new `STOP` commands during **DRAINING**.
+     *     - `START` commands during **DRAINING** must transition the instance back to
+     *       **PROCESSING**.
+     * If the effect instance is already in **IDLE** state, it must do nothing and return success.
+     *
+     * If the effect instance transitions to DRAINING state:
+     * 1. It must automatically transition to IDLE after completing draining tasks.
+     * 2. It must ignore any new STOP commands received during the DRAINING state.
+     * 3. START commands during DRAINING must immediately transfer the instance back to PROCESSING.
+     *
      */
     STOP = 1,
     /**
      * Keep all parameter settings but reset the buffer content, stop engine processing, and transit
-     * instance state to IDLE if its in PROCESSING state.
+     * the instance state to IDLE if it is in PROCESSING state.
      * Effect instance must be able to handle RESET command at IDLE and PROCESSING states.
+     *
+     * If the implementation includes intermediate operations such as draining, the RESET command
+     * must bypass DRAINING and immediately transition the state to IDLE.
      */
     RESET = 2,
 
diff --git a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
index b152f76..62e9bd4 100644
--- a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
@@ -70,6 +70,10 @@
      */
     const String EFFECT_TYPE_UUID_EQUALIZER = "0bed4300-ddd6-11db-8f34-0002a5d5c51b";
     /**
+     * UUID for Audio eraser effect type.
+     */
+    const String EFFECT_TYPE_UUID_ERASER = "fa81a9ac-588b-11ed-9b6a-0242ac120002";
+    /**
      * UUID for Haptic Generator type.
      */
     const String EFFECT_TYPE_UUID_HAPTIC_GENERATOR = "1411e6d6-aecd-4021-a1cf-a6aceb0d71e5";
diff --git a/audio/aidl/android/hardware/audio/effect/Eraser.aidl b/audio/aidl/android/hardware/audio/effect/Eraser.aidl
new file mode 100644
index 0000000..990c6c0
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Eraser.aidl
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+import android.media.audio.eraser.Capability;
+import android.media.audio.eraser.Configuration;
+import android.media.audio.eraser.Mode;
+
+/**
+ * The Audio Eraser Effect is an audio effect that combines multiple capabilities to manipulate and
+ * enhance audio streams.
+ *
+ * The Audio Eraser Effect integrates three primary components:
+ *
+ * Sound Separator: Detects and splits the input audio into multiple sound sources.
+ * Sound Classifier: Classifies each separated sound source into predefined categories based on the
+ * AudioSet ontology.
+ * Remixer: Adjusts the gain factor (volume) of each classified sound source according to specified
+ * configurations, then recombines them into a single output audio stream.
+ *
+ * The Audio Eraser Effect operates in different modes, each leveraging a subset of these
+ * components to achieve specific functionalities as defined in `android.media.audio.eraser.Mode`.
+ *
+ * Flow Diagrams for each operation mode as below.
+ *
+ * ERASER:
+ *                                                  +-----------------+
+ *                                              +-->| Sound Classifier|---+
+ *                                              |   +-----------------+   |
+ *                                              |                         |
+ *+----------------+       +----------------+   |   +-----------------+   |   +----------------+
+ *|   Input Audio  |------>| Sound Separator|---+-->| Sound Classifier|---+-->|    Remixer     |
+ *+----------------+       +----------------+   |   +-----------------+   |   +--------+-------+
+ *                                              |                         |            |
+ *                                              |   +-----------------+   |            |
+ *                                              +-->| Sound Classifier|---+            |
+ *                                                  +-----------------+                |
+ *                                                            |                        v
+ *                                                            v               +----------------+
+ *                                               {Classification Metadata}    |  Output Audio  |
+ *                                                                            +----------------+
+ *
+ * CLASSIFIER:
+ *+----------------+       +-----------------+       +-----------------+
+ *|   Input Audio  |------>| Sound Classifier|------>| Original Audio  |
+ *+----------------+       +-----------------+       +-----------------+
+ *                                  |
+ *                                  v
+ *                       {Classification Metadata}
+ *
+ */
+@VintfStability
+union Eraser {
+    /**
+     * Parameter Id with union tag to identify the parameters for getParameter().
+     */
+    @VintfStability
+    union Id {
+        VendorExtension vendorExtensionTag;
+        Eraser.Tag commonTag;
+    }
+
+    /**
+     * Vendor extension parameters which can be customized.
+     */
+    VendorExtension vendor;
+
+    /**
+     * Eraser capability, defines supported input/output data formats, available work modes, and
+     * the specific capabilities of the sound classifier and separator
+     */
+    Capability capability;
+
+    /**
+     * Eraser configuration, contains the list of configurations for the eraser effect.
+     */
+    Configuration configuration;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl b/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl
index 3cc5acb..f882d63 100644
--- a/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl
+++ b/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl
@@ -56,13 +56,51 @@
     @VintfStability
     parcelable HapticScale {
         /**
+         * Representation of undefined scale factor, applied by default for backwards compatibility.
+         */
+        const float UNDEFINED_SCALE_FACTOR = -1.0f;
+
+        /**
          * Audio track ID.
          */
         int id;
+
         /**
          * Haptic intensity.
+         *
+         * This represents haptics scale as fixed levels defined by VibrationScale. If the field
+         * scaleFactor is defined then this will be ignored in favor of scaleFactor, otherwise this
+         * will be used to define the intensity for the haptics.
          */
         VibratorScale scale = VibratorScale.MUTE;
+
+        /**
+         * Haptic scale factor.
+         *
+         * This is a continuous scale representation of VibratorScale, allowing flexible number of
+         * scale levels. If this field is defined then it will be used to define the intensity of
+         * the haptics, instead of the old VibratorScale field. If this field is undefined then the
+         * old VibratorScale field will be used.
+         *
+         * The value zero represents the same as VibratorScale.MUTE and the value one represents
+         * VibratorScale.NONE. Values in (0,1) should scale down, and values > 1 should scale up
+         * within hardware bounds. Negative values will be ignored.
+         */
+        float scaleFactor = -1.0f; // UNDEFINED_SCALE_FACTOR
+
+        /**
+         * Haptic adaptive scale factor.
+         *
+         * This is an additional scale value that should be applied on top of the vibrator scale to
+         * adapt to the device current state. This should be applied to linearly scale the haptic
+         * data after scale/scaleFactor is applied.
+         *
+         * The value zero mutes the haptics, even if the scale/scaleFactor are not set to MUTE/zero.
+         * The value one will not scale the haptics, and can be used as a constant for no-op.
+         * Values in (0,1) should scale down. Values > 1 should scale up within hardware bounds.
+         * Negative values will be ignored.
+         */
+        float adaptiveScaleFactor = -1.0f; // UNDEFINED_SCALE_FACTOR
     }
 
     /**
diff --git a/audio/aidl/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
index b80e6ac..75d4d9e 100644
--- a/audio/aidl/android/hardware/audio/effect/IFactory.aidl
+++ b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
@@ -74,13 +74,18 @@
 
     /**
      * Called by the framework to destroy the effect and free up all currently allocated resources.
-     * It is recommended to destroy the effect from the client side as soon as it is becomes unused.
+     * This method can be called at any time to destroy an effect instance. It is recommended to
+     * destroy the effect from the client side as soon as it becomes unused to free up resources.
      *
-     * The client must ensure effect instance is closed before destroy.
+     * The effect instance must handle any necessary cleanup and resource deallocation.
+     * If the effect is in the **PROCESSING** or **DRAINING** state, it must gracefully stop
+     * processing before destruction.
+     * The effect must ensure that all internal states are properly cleaned up to prevent resource
+     * leaks.
      *
      * @param handle The handle of effect instance to be destroyed.
      * @throws EX_ILLEGAL_ARGUMENT if the effect handle is not valid.
-     * @throws EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+     * @throws EX_ILLEGAL_STATE if the effect instance can not be destroyed.
      */
     void destroyEffect(in IEffect handle);
 }
diff --git a/audio/aidl/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/android/hardware/audio/effect/Parameter.aidl
index 6fd9161..d57e67d 100644
--- a/audio/aidl/android/hardware/audio/effect/Parameter.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Parameter.aidl
@@ -26,6 +26,7 @@
 import android.hardware.audio.effect.DynamicsProcessing;
 import android.hardware.audio.effect.EnvironmentalReverb;
 import android.hardware.audio.effect.Equalizer;
+import android.hardware.audio.effect.Eraser;
 import android.hardware.audio.effect.HapticGenerator;
 import android.hardware.audio.effect.LoudnessEnhancer;
 import android.hardware.audio.effect.NoiseSuppression;
@@ -111,6 +112,10 @@
          * Parameter tag defined for Spatializer parameters.
          */
         Spatializer.Id spatializerTag;
+        /**
+         * Parameter tag defined for eraser parameters.
+         */
+        Eraser.Id eraserTag;
     }
 
     /**
@@ -198,6 +203,8 @@
         Visualizer visualizer;
         Volume volume;
         Spatializer spatializer;
+        // Eraser added at android.hardware.audio.effect.V3
+        Eraser eraser;
     }
     Specific specific;
 
diff --git a/audio/aidl/android/hardware/audio/effect/Processing.aidl b/audio/aidl/android/hardware/audio/effect/Processing.aidl
index cb77350..928ce16 100644
--- a/audio/aidl/android/hardware/audio/effect/Processing.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Processing.aidl
@@ -17,6 +17,7 @@
 package android.hardware.audio.effect;
 
 import android.hardware.audio.effect.Descriptor;
+import android.media.audio.common.AudioDevice;
 import android.media.audio.common.AudioSource;
 import android.media.audio.common.AudioStreamType;
 import android.media.audio.common.AudioUuid;
@@ -30,6 +31,7 @@
     union Type {
         AudioStreamType streamType = AudioStreamType.INVALID;
         AudioSource source;
+        AudioDevice device;
     }
 
     /**
diff --git a/audio/aidl/android/hardware/audio/effect/State.aidl b/audio/aidl/android/hardware/audio/effect/State.aidl
index 85a4afc..ecd1bbe 100644
--- a/audio/aidl/android/hardware/audio/effect/State.aidl
+++ b/audio/aidl/android/hardware/audio/effect/State.aidl
@@ -24,18 +24,20 @@
  * it should transfer to IDLE state after handle the command successfully. Effect instance should
  * consume minimal resource and transfer to INIT state after it was close().
  *
- * Refer to State.gv for detailed state diagram.
+ * An effect instance can be destroyed from any state using `IFactory.destroyEffect()`.
+ *
+ * Refer to the state machine diagram `state.gv` for a detailed state diagram.
  */
 @VintfStability
 @Backing(type="byte")
 enum State {
-
     /**
      * An effect instance is in INIT state by default after it was created with
      * IFactory.createEffect(). When an effect instance is in INIT state, it should have instance
      * context initialized, and ready to handle IEffect.setParameter(), IEffect.open() as well as
      * all getter interfaces.
      *
+     * **Requirements in INIT state:**
      * In INIT state, effect instance must:
      * 1. Not handle any IEffect.command() and return EX_ILLEGAL_STATE with any Command.Id.
      * 2. Be able to handle all parameter setting with IEffect.setParameter().
@@ -43,28 +45,33 @@
      * IEffect.getState().
      * 4. Be able to handle IEffect.open() successfully after configuration.
      *
-     * Client is expected to do necessary configuration with IEffect.setParameter(), get all
-     * resource ready with IEffect.open(), and make sure effect instance transfer to IDLE state
-     * before sending commands with IEffect.command() interface. Effect instance must transfer
-     * from INIT to IDLE state after handle IEffect.open() call successfully.
+     * **State Transitions:**
+     * - Transitions to **IDLE** after successful `IEffect.open()`.
+     * - Remains in **INIT** on `IEffect.getState()` and `IEffect.getDescriptor()`.
+     * - Transitions to the final state on `IFactory.destroyEffect()`.
      */
     INIT,
+
     /**
      * An effect instance transfer to IDLE state after it was open successfully with IEffect.open()
      * in INIT state, or after it was stop/reset with Command.Id.STOP/RESET in PROCESSING state.
      *
-     * In IDLE state, effect instance must:
+     * **Requirements in IDLE state:**
      * 1. Be able to start effect processing engine with IEffect.command(Command.Id.START) call.
      * 2. Be able to handle all parameter setting with IEffect.setParameter().
      * 3. Be able to handle all getter interface calls like IEffect.getParameter() and
      * IEffect.getState().
      *
-     * The following state transfer can happen in IDLE state:
-     * 1. Transfer to PROCESSING if instance receive an START command and start processing data
-     * successfully.
-     * 2. Transfer to INIT if instance receive a close() call.
+     * **State Transitions:**
+     * - Transitions to **PROCESSING** on `IEffect.command(CommandId.START)` after starting
+     *   processing data successfully.
+     * - Transitions to **INIT** on `IEffect.close()`.
+     * - Remains in **IDLE** on `IEffect.getParameter()`, `IEffect.setParameter()`,
+     *   `IEffect.getDescriptor()`, `IEffect.command(CommandId.RESET)`, and `IEffect.reopen()`.
+     * - Transitions to the final state on `IFactory.destroyEffect()`.
      */
     IDLE,
+
     /**
      * An effect instance is in PROCESSING state after it receive an START command and start
      * processing data successfully. Effect instance will transfer from PROCESSING to IDLE state if
@@ -75,12 +82,52 @@
      * the case of a close() call received when instance in PROCESSING state, it should try to stop
      * processing and transfer to IDLE first before close().
      *
-     * In PROCESSING state, effect instance must:
+     * **Requirements in PROCESSING state:**
      * 1. Return EX_ILLEGAL_STATE if it's not able to handle any parameter settings at runtime.
      * 2. Be able to handle STOP and RESET for IEffect.command() interface, and return
      * EX_ILLEGAL_STATE for all other commands.
      * 3. Must be able to handle all get* interface calls like IEffect.getParameter() and
      * IEffect.getState().
+     *
+     * **State Transitions:**
+     * - Transitions to **IDLE** on `IEffect.command(CommandId.STOP)` ( if no draining is required
+     *   or implemented) or `IEffect.command(CommandId.RESET)`.
+     * - Transitions to **DRAINING** on `IEffect.command(CommandId.STOP)` if draining is required.
+     * - Remains in **PROCESSING** on `IEffect.getParameter()`, `IEffect.setParameter()`,
+     *   `IEffect.getDescriptor()`, and `IEffect.reopen()`.
+     *
+     * **Notes:**
+     * - Clients should avoid calling `IEffect.close()` directly in this state; instead, they should
+     *   stop processing with `CommandId.STOP` before closing.
+     * - If `IEffect.close()` is called in this state, the effect instance should stop processing,
+     *   transition to **IDLE**, and then close.
+     * - Transitions to the final state on `IFactory.destroyEffect()`.
      */
     PROCESSING,
+
+    /**
+     * DRAINING is an optional transitional state where the effect instance completes processing
+     * remaining input buffers or finalizes operations (e.g., fading) before stopping completely.
+     * This state is typically entered after a `CommandId.STOP` command in the PROCESSING state when
+     * draining is required.
+     *
+     * **Requirements in DRAINING state:**
+     * 1. Must handle `CommandId.START` and transition back to **PROCESSING**.
+     * 2. Must handle getter interface calls like `IEffect.getParameter()` and `IEffect.getState()`.
+     * 3. Must automatically transition to **IDLE** after draining is complete.
+     *
+     * **State Transitions:**
+     * - Transitions to **PROCESSING** on `IEffect.command(CommandId.START)`.
+     * - Transitions to **IDLE** on `IEffect.command(CommandId.RESET)`.
+     * - Transitions to **IDLE** automatically after draining is complete.
+     * - Remains in **DRAINING** on `IEffect.getParameter()`, `IEffect.setParameter()`,
+     *   `IEffect.getDescriptor()`, and `IEffect.reopen()`.
+     *
+     * **Notes:**
+     * - If not implemented, the effect instance may transition directly from **PROCESSING** to
+     *   **IDLE** without this intermediate state.
+     * - Any `CommandId.STOP` commands received during **DRAINING** should be ignored.
+     * - Transitions to the final state on `IFactory.destroyEffect()`.
+     */
+    DRAINING,
 }
diff --git a/audio/aidl/android/hardware/audio/effect/Visualizer.aidl b/audio/aidl/android/hardware/audio/effect/Visualizer.aidl
index 0b37546..fe8fe97 100644
--- a/audio/aidl/android/hardware/audio/effect/Visualizer.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Visualizer.aidl
@@ -20,10 +20,12 @@
 
 /**
  * Visualizer specific definitions. Visualizer enables application to retrieve part of the currently
- * playing audio for visualization purpose
+ * playing audio for visualization purpose. The output is identical to the input, while
+ * visualization data is generated separately based on scalingMode and captureSamples parameter
+ * values.
  *
  * All parameter settings must be inside the range of Capability.Range.visualizer definition if the
- * definition for the corresponding parameter tag exist. See more detals about Range in Range.aidl.
+ * definition for the corresponding parameter tag exist. See more details about Range in Range.aidl.
  *
  */
 @VintfStability
@@ -50,14 +52,24 @@
     enum ScalingMode {
         /**
          * Defines a capture mode where amplification is applied based on the content of the
-         * captured data. This is the default Visualizer mode, and is suitable for music
-         * visualization.
+         * captured data in order to normalize it to the unsigned 8 bit sample range. This is the
+         * default Visualizer mode, and is suitable for music visualization.
+         *
+         * For example,
+         * Input Range:[-0.5, 0.5] -> Visualization Data Range:[0, 255]
+         * Input Range:[-1,1]      -> Visualization Data Range:[0, 255]
+         *
          */
         NORMALIZED = 0,
         /**
-         * Defines a capture mode where the playback volume will affect (scale) the range of the
-         * captured data. A low playback volume will lead to low sample and fft values, and
-         * vice-versa.
+         * Defines a capture mode where no additional scaling is done on the input audio data thus
+         * the visualization data remains as close as possible to the input. The visualization
+         * directly reflects the actual loudness and waveform shape, rather than fitting everything
+         * into a normalized visual range.
+         *
+         * For example,
+         * Input Range:[-0.5, 0.5] -> Visualization Data Range:[64, 192]
+         * Input Range:[-1,1]      -> Visualization Data Range:[0, 255]
          */
         AS_PLAYED,
     }
@@ -93,7 +105,10 @@
     Measurement measurement;
 
     /**
-     * Get only parameter to get the latest captured samples of PCM samples (8 bits per sample).
+     * Get only parameter to get the latest captured samples of PCM samples (8 bits per sample). It
+     * represents the visualization data. The capture is intended for passing to applications, and
+     * it contains the same audio data as the input, but with intentionally lower sample resolution,
+     * and optionally normalized, depending on the scalingMode.
      */
     byte[] captureSampleBuffer;
 
diff --git a/audio/aidl/android/hardware/audio/effect/state.gv b/audio/aidl/android/hardware/audio/effect/state.gv
index 22c70c8..8590296 100644
--- a/audio/aidl/android/hardware/audio/effect/state.gv
+++ b/audio/aidl/android/hardware/audio/effect/state.gv
@@ -16,23 +16,43 @@
 
 // To render: "dot -Tpng state.gv -o state.png"
 digraph effect_state_machine {
-    node[shape = point style = filled fillcolor = black width = 0.5] I;
-    node[shape = doublecircle] F;
-    node[shape = oval width = 1];
-    node[fillcolor = lightgreen] INIT;
-    node[fillcolor = lightblue] IDLE;
-    node[fillcolor = lightyellow] PROCESSING;
 
-    I -> INIT[label = "IFactory.createEffect" labelfontcolor = "navy"];
-    INIT -> F[label = "IFactory.destroyEffect"];
-    INIT -> IDLE[label = "IEffect.open()" labelfontcolor = "lime"];
-    IDLE -> PROCESSING[label = "IEffect.command(START"];
-    PROCESSING -> IDLE[label = "IEffect.command(STOP)\nIEffect.command(RESET)"];
-    IDLE -> INIT[label = "IEffect.close()"];
+    rankdir=LR; // Left to Right layout
 
-    INIT -> INIT[label = "IEffect.getState\nIEffect.getDescriptor"];
-    IDLE -> IDLE[label = "IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor\nIEffect.command(RESET)\nIEffect.reopen"];
-    PROCESSING
-            -> PROCESSING
-                    [label = "IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor\nIEffect.reopen"];
+    label="Effect State Machine";
+    fontsize=20;
+    labelloc=top;
+
+    node [fontname="Helvetica", fontsize=12, style=filled];
+
+    // Initial state node
+    I [shape=point, fillcolor=black, width=0.2];
+
+    // Final state node
+    F [shape=doublecircle, label="Destroyed"];
+
+    // Define other nodes with colors
+    INIT [shape=ellipse, fillcolor=lightgreen, label="INIT"];
+    IDLE [shape=ellipse, fillcolor=lightblue, label="IDLE"];
+    PROCESSING [shape=ellipse, fillcolor=lightyellow, label="PROCESSING"];
+    DRAINING [shape=ellipse, fillcolor=lightgrey, label="DRAINING"];
+    ANY_STATE [shape=ellipse, style=dashed, label="Any State", fillcolor=white];
+
+    // Main transitions
+    I -> INIT [label="IFactory.createEffect", fontcolor="navy"];
+    INIT -> IDLE [label="IEffect.open()", fontcolor="lime"];
+    IDLE -> PROCESSING [label="IEffect.command(START)"];
+    PROCESSING -> IDLE [label="IEffect.command(STOP) (if draining not required)\nIEffect.command(RESET)"];
+    PROCESSING -> DRAINING [label="IEffect.command(STOP) (if draining required)", fontcolor="orange"];
+    DRAINING -> IDLE [label="IEffect.command(RESET)\nDraining complete (automatic transition)"];
+    DRAINING -> PROCESSING [label="IEffect.command(START) (Interrupt draining)"];
+    IDLE -> INIT [label="IEffect.close()"];
+
+    // Global transitions
+    subgraph cluster_global_transitions {
+        label="Global Transitions (Any State)";
+        style=dashed;
+        ANY_STATE -> F [label="IFactory.destroyEffect", style="bold"];
+        ANY_STATE -> ANY_STATE [label="IEffect.getParameter\nIEffect.setParameter\nIEffect.getDescriptor\nIEffect.getState\nIEffect.reopen", fontsize=10];
+    }
 }
diff --git a/audio/aidl/common/Android.bp b/audio/aidl/common/Android.bp
index 5c0c685..c14d19d 100644
--- a/audio/aidl/common/Android.bp
+++ b/audio/aidl/common/Android.bp
@@ -32,10 +32,12 @@
     header_libs: [
         "libbase_headers",
         "libsystem_headers",
+        "libutils_headers",
     ],
     export_header_lib_headers: [
         "libbase_headers",
         "libsystem_headers",
+        "libutils_headers",
     ],
     srcs: [
         "StreamWorker.cpp",
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
index 6241f44..52ae936 100644
--- a/audio/aidl/common/include/Utils.h
+++ b/audio/aidl/common/include/Utils.h
@@ -31,6 +31,7 @@
 #include <aidl/android/media/audio/common/AudioOutputFlags.h>
 #include <aidl/android/media/audio/common/PcmType.h>
 #include <android/binder_auto_utils.h>
+#include <utils/FastStrcmp.h>
 
 namespace ndk {
 
@@ -61,6 +62,11 @@
         ::aidl::android::media::audio::common::AudioMode::CALL_SCREEN,
 };
 
+constexpr bool iequals(const std::string& str1, const std::string& str2) {
+    return str1.length() == str2.length() &&
+           !fasticmp<strncmp>(str1.c_str(), str2.c_str(), str1.length());
+}
+
 constexpr size_t getPcmSampleSizeInBytes(::aidl::android::media::audio::common::PcmType pcm) {
     using ::aidl::android::media::audio::common::PcmType;
     switch (pcm) {
diff --git a/audio/aidl/common/tests/utils_tests.cpp b/audio/aidl/common/tests/utils_tests.cpp
index 1b8b8df..1522d7e 100644
--- a/audio/aidl/common/tests/utils_tests.cpp
+++ b/audio/aidl/common/tests/utils_tests.cpp
@@ -86,7 +86,7 @@
             std::make_pair(6UL, AudioChannelLayout::LAYOUT_5POINT1),
             std::make_pair(8UL, AudioChannelLayout::LAYOUT_7POINT1),
             std::make_pair(16UL, AudioChannelLayout::LAYOUT_9POINT1POINT6),
-            std::make_pair(13UL, AudioChannelLayout::LAYOUT_13POINT_360RA),
+            std::make_pair(13UL, AudioChannelLayout::LAYOUT_13POINT0),
             std::make_pair(24UL, AudioChannelLayout::LAYOUT_22POINT2),
             std::make_pair(3UL, AudioChannelLayout::LAYOUT_STEREO_HAPTIC_A),
             std::make_pair(4UL, AudioChannelLayout::LAYOUT_STEREO_HAPTIC_AB)};
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index a3db45f..73d7626 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -54,6 +54,7 @@
         "AidlConversionXsdc.cpp",
         "AudioPolicyConfigXmlConverter.cpp",
         "Bluetooth.cpp",
+        "CapEngineConfigXmlConverter.cpp",
         "Config.cpp",
         "Configuration.cpp",
         "EngineConfigXmlConverter.cpp",
@@ -61,7 +62,6 @@
         "ModulePrimary.cpp",
         "SoundDose.cpp",
         "Stream.cpp",
-        "StreamSwitcher.cpp",
         "Telephony.cpp",
         "XsdcConversion.cpp",
         "alsa/Mixer.cpp",
@@ -71,6 +71,7 @@
         "bluetooth/DevicePortProxy.cpp",
         "bluetooth/ModuleBluetooth.cpp",
         "bluetooth/StreamBluetooth.cpp",
+        "deprecated/StreamSwitcher.cpp",
         "primary/PrimaryMixer.cpp",
         "primary/StreamPrimary.cpp",
         "r_submix/ModuleRemoteSubmix.cpp",
@@ -84,14 +85,17 @@
         "usb/UsbAlsaMixerControl.cpp",
     ],
     generated_sources: [
+        "audio_policy_capengine_configuration_aidl_default",
         "audio_policy_configuration_aidl_default",
         "audio_policy_engine_configuration_aidl_default",
     ],
     generated_headers: [
+        "audio_policy_capengine_configuration_aidl_default",
         "audio_policy_configuration_aidl_default",
         "audio_policy_engine_configuration_aidl_default",
     ],
     export_generated_headers: [
+        "audio_policy_capengine_configuration_aidl_default",
         "audio_policy_configuration_aidl_default",
         "audio_policy_engine_configuration_aidl_default",
     ],
@@ -204,6 +208,7 @@
     ],
     vendor: true,
     shared_libs: [
+        "libaudio_aidl_conversion_common_ndk",
         "libaudioaidlcommon",
         "libaudioutils",
         "libbase",
@@ -225,6 +230,7 @@
         "-Wextra",
         "-Werror",
         "-Wthread-safety",
+        "-DBACKEND_NDK",
     ],
 }
 
diff --git a/audio/aidl/default/CapEngineConfigXmlConverter.cpp b/audio/aidl/default/CapEngineConfigXmlConverter.cpp
new file mode 100644
index 0000000..20fbca4
--- /dev/null
+++ b/audio/aidl/default/CapEngineConfigXmlConverter.cpp
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_Config"
+
+#include <aidl/android/media/audio/common/AudioProductStrategyType.h>
+#include <android-base/logging.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/TypeConverter.h>
+#include <media/convert.h>
+#include <utils/FastStrcmp.h>
+
+#include "core-impl/CapEngineConfigXmlConverter.h"
+#include "core-impl/XsdcConversion.h"
+
+using aidl::android::hardware::audio::common::iequals;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioHalCapConfiguration;
+using aidl::android::media::audio::common::AudioHalCapCriterionV2;
+using aidl::android::media::audio::common::AudioHalCapDomain;
+using aidl::android::media::audio::common::AudioHalCapParameter;
+using aidl::android::media::audio::common::AudioHalCapRule;
+using aidl::android::media::audio::common::AudioPolicyForceUse;
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::AudioStreamType;
+
+using ::android::BAD_VALUE;
+using ::android::base::unexpected;
+using ::android::utilities::convertTo;
+
+namespace eng_xsd = android::audio::policy::capengine::configuration;
+
+namespace aidl::android::hardware::audio::core::internal {
+
+static constexpr const char* gStrategiesParameter = "product_strategies";
+static constexpr const char* gInputSourcesParameter = "input_sources";
+static constexpr const char* gStreamsParameter = "streams";
+static constexpr const char* gOutputDevicesParameter = "selected_output_devices";
+static constexpr const char* gOutputDeviceAddressParameter = "device_address";
+static constexpr const char* gStrategyPrefix = "vx_";
+static constexpr const char* gLegacyOutputDevicePrefix = "AUDIO_DEVICE_OUT_";
+static constexpr const char* gLegacyInputDevicePrefix = "AUDIO_DEVICE_IN_";
+static constexpr const char* gLegacyStreamPrefix = "AUDIO_STREAM_";
+static constexpr const char* gLegacySourcePrefix = "AUDIO_SOURCE_";
+
+std::optional<std::vector<std::optional<AudioHalCapDomain>>>&
+CapEngineConfigXmlConverter::getAidlCapEngineConfig() {
+    return mAidlCapDomains;
+}
+
+ConversionResult<AudioHalCapRule::CriterionRule> convertCriterionRuleToAidl(
+        const eng_xsd::SelectionCriterionRuleType& xsdcRule) {
+    using Tag = AudioHalCapCriterionV2::Tag;
+    AudioHalCapRule::CriterionRule rule{};
+    std::string criterionName = xsdcRule.getSelectionCriterion();
+    std::string criterionValue = xsdcRule.getValue();
+    if (iequals(criterionName, toString(Tag::availableInputDevices))) {
+        AudioHalCapCriterionV2::AvailableDevices value;
+        value.values.emplace_back(VALUE_OR_RETURN(
+                convertDeviceTypeToAidl(gLegacyInputDevicePrefix + criterionValue)));
+        rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::availableInputDevices>(value);
+
+    } else if (iequals(criterionName, toString(Tag::availableOutputDevices))) {
+        AudioHalCapCriterionV2::AvailableDevices value;
+        value.values.emplace_back(VALUE_OR_RETURN(
+                convertDeviceTypeToAidl(gLegacyOutputDevicePrefix + criterionValue)));
+        rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::availableOutputDevices>(value);
+    } else if (iequals(criterionName, toString(Tag::availableInputDevicesAddresses))) {
+        AudioHalCapCriterionV2::AvailableDevicesAddresses value;
+        value.values.emplace_back(criterionValue);
+        rule.criterionAndValue =
+                AudioHalCapCriterionV2::make<Tag::availableInputDevicesAddresses>(value);
+    } else if (iequals(criterionName, toString(Tag::availableOutputDevicesAddresses))) {
+        AudioHalCapCriterionV2::AvailableDevicesAddresses value;
+        value.values.emplace_back(criterionValue);
+        rule.criterionAndValue =
+                AudioHalCapCriterionV2::make<Tag::availableOutputDevicesAddresses>(value);
+    } else if (iequals(criterionName, toString(Tag::telephonyMode))) {
+        AudioHalCapCriterionV2::TelephonyMode value;
+        value.values.emplace_back(VALUE_OR_RETURN(convertTelephonyModeToAidl(criterionValue)));
+        rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::telephonyMode>(value);
+    } else if (!fastcmp<strncmp>(criterionName.c_str(), kXsdcForceConfigForUse,
+            strlen(kXsdcForceConfigForUse))) {
+        AudioHalCapCriterionV2::ForceConfigForUse value;
+        value.values.emplace_back(
+                VALUE_OR_RETURN(convertForceUseToAidl(criterionName, criterionValue)));
+        rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(value);
+    } else {
+        LOG(ERROR) << __func__ << " unrecognized criterion " << criterionName;
+        return unexpected(BAD_VALUE);
+    }
+    if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::Excludes) {
+        rule.matchingRule = AudioHalCapRule::MatchingRule::EXCLUDES;
+    } else if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::Includes) {
+        rule.matchingRule = AudioHalCapRule::MatchingRule::INCLUDES;
+    } else if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::Is) {
+        rule.matchingRule = AudioHalCapRule::MatchingRule::IS;
+    } else if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::IsNot) {
+        rule.matchingRule = AudioHalCapRule::MatchingRule::IS_NOT;
+    } else {
+        LOG(ERROR) << "Unsupported match when rule.";
+        return unexpected(BAD_VALUE);
+    }
+    return rule;
+}
+
+ConversionResult<AudioHalCapRule> convertRule(const eng_xsd::CompoundRuleType& xsdcCompoundRule) {
+    AudioHalCapRule rule{};
+    bool isPreviousCompoundRule = true;
+    if (xsdcCompoundRule.getType() == eng_xsd::TypeEnum::Any) {
+        rule.compoundRule = AudioHalCapRule::CompoundRule::ANY;
+    } else if (xsdcCompoundRule.getType() == eng_xsd::TypeEnum::All) {
+        rule.compoundRule = AudioHalCapRule::CompoundRule::ALL;
+    } else {
+        LOG(ERROR) << "Unsupported compound rule type.";
+        return unexpected(BAD_VALUE);
+    }
+    for (const auto& childXsdcCoumpoundRule : xsdcCompoundRule.getCompoundRule_optional()) {
+        if (childXsdcCoumpoundRule.hasCompoundRule_optional()) {
+            rule.nestedRules.push_back(VALUE_OR_FATAL(convertRule(childXsdcCoumpoundRule)));
+        } else if (childXsdcCoumpoundRule.hasSelectionCriterionRule_optional()) {
+            rule.nestedRules.push_back(VALUE_OR_FATAL(convertRule(childXsdcCoumpoundRule)));
+        }
+    }
+    if (xsdcCompoundRule.hasSelectionCriterionRule_optional()) {
+        for (const auto& xsdcRule : xsdcCompoundRule.getSelectionCriterionRule_optional()) {
+            rule.criterionRules.push_back(VALUE_OR_FATAL(convertCriterionRuleToAidl(xsdcRule)));
+        }
+    }
+    return rule;
+}
+
+ConversionResult<int> getAudioProductStrategyId(const std::string& path) {
+    std::vector<std::string> strings;
+    std::istringstream pathStream(path);
+    std::string stringToken;
+    while (getline(pathStream, stringToken, '/')) {
+        std::size_t pos = stringToken.find(gStrategyPrefix);
+        if (pos != std::string::npos) {
+            std::string strategyIdLiteral = stringToken.substr(pos + std::strlen(gStrategyPrefix));
+            int strategyId;
+            if (!convertTo(strategyIdLiteral, strategyId)) {
+                LOG(ERROR) << "Invalid strategy " << stringToken << " from path " << path;
+                return unexpected(BAD_VALUE);
+            }
+            return strategyId;
+        }
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioSource> getAudioSource(const std::string& path) {
+    std::vector<std::string> strings;
+    std::istringstream pathStream(path);
+    std::string stringToken;
+    while (getline(pathStream, stringToken, '/')) {
+        if (stringToken.find(gInputSourcesParameter) != std::string::npos) {
+            getline(pathStream, stringToken, '/');
+            std::transform(stringToken.begin(), stringToken.end(), stringToken.begin(),
+                           [](char c) { return std::toupper(c); });
+            std::string legacySourceLiteral = "AUDIO_SOURCE_" + stringToken;
+            audio_source_t legacySource;
+            if (!::android::SourceTypeConverter::fromString(legacySourceLiteral, legacySource)) {
+                LOG(ERROR) << "Invalid source " << stringToken << " from path " << path;
+                return unexpected(BAD_VALUE);
+            }
+            return legacy2aidl_audio_source_t_AudioSource(legacySource);
+        }
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioStreamType> getAudioStreamType(const std::string& path) {
+    std::vector<std::string> strings;
+    std::istringstream pathStream(path);
+    std::string stringToken;
+
+    while (getline(pathStream, stringToken, '/')) {
+        if (stringToken.find(gStreamsParameter) != std::string::npos) {
+            getline(pathStream, stringToken, '/');
+            std::transform(stringToken.begin(), stringToken.end(), stringToken.begin(),
+                           [](char c) { return std::toupper(c); });
+            std::string legacyStreamLiteral = std::string(gLegacyStreamPrefix) + stringToken;
+            audio_stream_type_t legacyStream;
+            if (!::android::StreamTypeConverter::fromString(legacyStreamLiteral, legacyStream)) {
+                LOG(ERROR) << "Invalid stream " << stringToken << " from path " << path;
+                return unexpected(BAD_VALUE);
+            }
+            return legacy2aidl_audio_stream_type_t_AudioStreamType(legacyStream);
+        }
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<std::string> toUpperAndAppendPrefix(const std::string& capName,
+                                                     const std::string& legacyPrefix) {
+    std::string legacyName = capName;
+    std::transform(legacyName.begin(), legacyName.end(), legacyName.begin(),
+                   [](char c) { return std::toupper(c); });
+    return legacyPrefix + legacyName;
+}
+
+ConversionResult<AudioHalCapParameter> CapEngineConfigXmlConverter::convertParamToAidl(
+        const eng_xsd::ConfigurableElementSettingsType& element) {
+    const auto& path = element.getPath();
+
+    AudioHalCapParameter parameterSetting;
+    if (path.find(gStrategiesParameter) != std::string::npos) {
+        int strategyId = VALUE_OR_FATAL(getAudioProductStrategyId(path));
+        if (path.find(gOutputDevicesParameter) != std::string::npos) {
+            // Value is 1 or 0
+            if (!element.hasBitParameter_optional()) {
+                LOG(ERROR) << "Invalid strategy value type";
+                return unexpected(BAD_VALUE);
+            }
+            // Convert name to output device type
+            const auto* xsdcParam = element.getFirstBitParameter_optional();
+            std::string outputDevice = VALUE_OR_FATAL(toUpperAndAppendPrefix(
+                    eng_xsd::toString(xsdcParam->getName()), gLegacyOutputDevicePrefix));
+            audio_devices_t legacyType;
+            if (!::android::OutputDeviceConverter::fromString(outputDevice, legacyType)) {
+                LOG(ERROR) << "Invalid strategy device type " << outputDevice;
+                return unexpected(BAD_VALUE);
+            }
+            AudioDeviceDescription aidlDevice =
+                    VALUE_OR_FATAL(legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
+            bool isSelected;
+            if (!convertTo(xsdcParam->getValue(), isSelected)) {
+                LOG(ERROR) << "Invalid strategy device selection value " << xsdcParam->getValue();
+                return unexpected(BAD_VALUE);
+            }
+            parameterSetting =
+                    AudioHalCapParameter::StrategyDevice(aidlDevice, strategyId, isSelected);
+        } else if (path.find(gOutputDeviceAddressParameter) != std::string::npos) {
+            // Value is the address
+            if (!element.hasStringParameter_optional()) {
+                return unexpected(BAD_VALUE);
+            }
+            std::string address = element.getFirstStringParameter_optional()->getValue();
+            parameterSetting = AudioHalCapParameter::StrategyDeviceAddress(
+                    AudioDeviceAddress(address), strategyId);
+        }
+    } else if (path.find(gInputSourcesParameter) != std::string::npos) {
+        // Value is 1 or 0
+        if (!element.hasBitParameter_optional()) {
+            LOG(ERROR) << "Invalid source value type";
+            return unexpected(BAD_VALUE);
+        }
+        AudioSource audioSourceAidl = VALUE_OR_FATAL(getAudioSource(path));
+        const auto* xsdcParam = element.getFirstBitParameter_optional();
+        std::string inputDeviceLiteral = VALUE_OR_FATAL(toUpperAndAppendPrefix(
+                eng_xsd::toString(xsdcParam->getName()), gLegacyInputDevicePrefix));
+        audio_devices_t inputDeviceType;
+        if (!::android::InputDeviceConverter::fromString(inputDeviceLiteral, inputDeviceType)) {
+            LOG(ERROR) << "Invalid source device type " << inputDeviceLiteral;
+            return unexpected(BAD_VALUE);
+        }
+        AudioDeviceDescription aidlDevice =
+                VALUE_OR_FATAL(legacy2aidl_audio_devices_t_AudioDeviceDescription(inputDeviceType));
+
+        bool isSelected;
+        if (!convertTo(xsdcParam->getValue(), isSelected)) {
+            LOG(ERROR) << "Invalid source value type " << xsdcParam->getValue();
+            return unexpected(BAD_VALUE);
+        }
+        parameterSetting =
+                AudioHalCapParameter::InputSourceDevice(aidlDevice, audioSourceAidl, isSelected);
+    } else if (path.find(gStreamsParameter) != std::string::npos) {
+        AudioStreamType audioStreamAidl = VALUE_OR_FATAL(getAudioStreamType(path));
+        if (!element.hasEnumParameter_optional()) {
+            LOG(ERROR) << "Invalid stream value type";
+            return unexpected(BAD_VALUE);
+        }
+        const auto* xsdcParam = element.getFirstEnumParameter_optional();
+        std::string profileLiteral =
+                VALUE_OR_FATAL(toUpperAndAppendPrefix(xsdcParam->getValue(), gLegacyStreamPrefix));
+        audio_stream_type_t profileLegacyStream;
+        if (!::android::StreamTypeConverter::fromString(profileLiteral, profileLegacyStream)) {
+            LOG(ERROR) << "Invalid stream value " << profileLiteral;
+            return unexpected(BAD_VALUE);
+        }
+        AudioStreamType profileStreamAidl = VALUE_OR_FATAL(
+                legacy2aidl_audio_stream_type_t_AudioStreamType(profileLegacyStream));
+        parameterSetting =
+                AudioHalCapParameter::StreamVolumeProfile(audioStreamAidl, profileStreamAidl);
+    }
+    return parameterSetting;
+}
+
+ConversionResult<std::vector<AudioHalCapParameter>>
+CapEngineConfigXmlConverter::convertSettingToAidl(
+        const eng_xsd::SettingsType::Configuration& xsdcSetting) {
+    std::vector<AudioHalCapParameter> aidlCapParameterSettings;
+    for (const auto& element : xsdcSetting.getConfigurableElement()) {
+        aidlCapParameterSettings.push_back(VALUE_OR_FATAL(convertParamToAidl(element)));
+    }
+    return aidlCapParameterSettings;
+}
+
+ConversionResult<AudioHalCapConfiguration> CapEngineConfigXmlConverter::convertConfigurationToAidl(
+        const eng_xsd::ConfigurationsType::Configuration& xsdcConfiguration,
+        const eng_xsd::SettingsType::Configuration& xsdcSettingConfiguration) {
+    AudioHalCapConfiguration aidlCapConfiguration;
+    aidlCapConfiguration.name = xsdcConfiguration.getName();
+    if (xsdcConfiguration.hasCompoundRule()) {
+        if (xsdcConfiguration.getCompoundRule().size() != 1) {
+            return unexpected(BAD_VALUE);
+        }
+        aidlCapConfiguration.rule =
+                VALUE_OR_FATAL(convertRule(xsdcConfiguration.getCompoundRule()[0]));
+        aidlCapConfiguration.parameterSettings =
+                VALUE_OR_FATAL(convertSettingToAidl(xsdcSettingConfiguration));
+    }
+    return aidlCapConfiguration;
+}
+
+ConversionResult<eng_xsd::SettingsType::Configuration> getConfigurationByName(
+        const std::string& name, const std::vector<eng_xsd::SettingsType>& xsdcSettingsVec) {
+    for (const auto& xsdcSettings : xsdcSettingsVec) {
+        for (const auto& xsdcConfiguration : xsdcSettings.getConfiguration()) {
+            if (xsdcConfiguration.getName() == name) {
+                return xsdcConfiguration;
+            }
+        }
+    }
+    LOG(ERROR) << __func__ << " failed to find configuration " << name;
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<std::vector<AudioHalCapConfiguration>>
+CapEngineConfigXmlConverter::convertConfigurationsToAidl(
+        const std::vector<eng_xsd::ConfigurationsType>& xsdcConfigurationsVec,
+        const std::vector<eng_xsd::SettingsType>& xsdcSettingsVec) {
+    if (xsdcConfigurationsVec.empty() || xsdcSettingsVec.empty()) {
+        LOG(ERROR) << __func__ << " empty configurations/settings";
+        return unexpected(BAD_VALUE);
+    }
+    std::vector<AudioHalCapConfiguration> aidlConfigurations;
+    for (const auto& xsdcConfigurations : xsdcConfigurationsVec) {
+        for (const auto& xsdcConfiguration : xsdcConfigurations.getConfiguration()) {
+            auto xsdcSettingConfiguration = VALUE_OR_FATAL(
+                    getConfigurationByName(xsdcConfiguration.getName(), xsdcSettingsVec));
+            aidlConfigurations.push_back(VALUE_OR_FATAL(
+                    convertConfigurationToAidl(xsdcConfiguration, xsdcSettingConfiguration)));
+        }
+    }
+    return aidlConfigurations;
+}
+
+ConversionResult<AudioHalCapDomain> CapEngineConfigXmlConverter::convertConfigurableDomainToAidl(
+        const eng_xsd::ConfigurableDomainType& xsdcConfigurableDomain) {
+    AudioHalCapDomain aidlConfigurableDomain;
+
+    aidlConfigurableDomain.name = xsdcConfigurableDomain.getName();
+    if (xsdcConfigurableDomain.hasSequenceAware() && xsdcConfigurableDomain.getSequenceAware()) {
+        LOG(ERROR) << "sequence aware not supported.";
+        return unexpected(BAD_VALUE);
+    }
+    if (xsdcConfigurableDomain.hasConfigurations() && xsdcConfigurableDomain.hasSettings()) {
+        aidlConfigurableDomain.configurations = VALUE_OR_FATAL(convertConfigurationsToAidl(
+                xsdcConfigurableDomain.getConfigurations(), xsdcConfigurableDomain.getSettings()));
+    }
+    return aidlConfigurableDomain;
+}
+
+void CapEngineConfigXmlConverter::init() {
+    if (getXsdcConfig()->hasConfigurableDomain()) {
+        mAidlCapDomains = std::make_optional<>(VALUE_OR_FATAL(
+                (convertCollectionToAidlOptionalValues<eng_xsd::ConfigurableDomainType,
+                                                       AudioHalCapDomain>(
+                        getXsdcConfig()->getConfigurableDomain(),
+                        std::bind(&CapEngineConfigXmlConverter::convertConfigurableDomainToAidl,
+                                  this, std::placeholders::_1)))));
+    } else {
+        mAidlCapDomains = std::nullopt;
+    }
+}
+
+}  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index 54e2d18..0ff8eb4 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -324,9 +324,9 @@
 //
 // Mix ports:
 //  * "r_submix output", maximum 10 opened streams, maximum 10 active streams
-//    - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000, 192000
 //  * "r_submix input", maximum 10 opened streams, maximum 10 active streams
-//    - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000, 192000
 //
 // Routes:
 //  "r_submix output" -> "Remote Submix Out"
@@ -337,7 +337,7 @@
         Configuration c;
         const std::vector<AudioProfile> remoteSubmixPcmAudioProfiles{
                 createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO},
-                              {8000, 11025, 16000, 32000, 44100, 48000})};
+                              {8000, 11025, 16000, 32000, 44100, 48000, 192000})};
 
         // Device ports
 
diff --git a/audio/aidl/default/EffectConfig.cpp b/audio/aidl/default/EffectConfig.cpp
index eb0c015..9c335ba 100644
--- a/audio/aidl/default/EffectConfig.cpp
+++ b/audio/aidl/default/EffectConfig.cpp
@@ -18,6 +18,8 @@
 #include <string>
 #define LOG_TAG "AHAL_EffectConfig"
 #include <android-base/logging.h>
+#include <media/AidlConversionCppNdk.h>
+#include <system/audio.h>
 #include <system/audio_aidl_utils.h>
 #include <system/audio_effects/audio_effects_conf.h>
 #include <system/audio_effects/effect_uuid.h>
@@ -28,6 +30,10 @@
 #include <android/apexsupport.h>
 #endif
 
+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::AudioSource;
 using aidl::android::media::audio::common::AudioStreamType;
 using aidl::android::media::audio::common::AudioUuid;
@@ -76,6 +82,14 @@
                 registerFailure(parseProcessing(Processing::Type::streamType, xmlStream));
             }
         }
+
+        // Parse device effect chains
+        for (auto& xmlDeviceEffects : getChildren(xmlConfig, "deviceEffects")) {
+            for (auto& xmlDevice : getChildren(xmlDeviceEffects, "device")) {
+                // AudioDevice
+                registerFailure(parseProcessing(Processing::Type::device, xmlDevice));
+            }
+        }
     }
     LOG(DEBUG) << __func__ << " successfully parsed " << file << ", skipping " << mSkippedElements
                << " element(s)";
@@ -195,7 +209,8 @@
 }
 
 std::optional<Processing::Type> EffectConfig::stringToProcessingType(Processing::Type::Tag typeTag,
-                                                                     const std::string& type) {
+                                                                     const std::string& type,
+                                                                     const std::string& address) {
     // see list of audio stream types in audio_stream_type_t:
     // system/media/audio/include/system/audio_effects/audio_effects_conf.h
     // AUDIO_STREAM_DEFAULT_TAG is not listed here because according to SYS_RESERVED_DEFAULT in
@@ -238,6 +253,19 @@
         if (typeIter != sAudioSourceTable.end()) {
             return typeIter->second;
         }
+    } else if (typeTag == Processing::Type::device) {
+        audio_devices_t deviceType;
+        if (!audio_device_from_string(type.c_str(), &deviceType)) {
+            LOG(ERROR) << __func__ << "DeviceEffect: invalid type " << type;
+            return std::nullopt;
+        }
+        auto ret = ::aidl::android::legacy2aidl_audio_device_AudioDevice(deviceType, address);
+        if (!ret.ok()) {
+            LOG(ERROR) << __func__ << "DeviceEffect: Failed to get AudioDevice from type "
+                    << deviceType << ", address " << address;
+            return std::nullopt;
+        }
+        return ret.value();
     }
 
     return std::nullopt;
@@ -246,7 +274,10 @@
 bool EffectConfig::parseProcessing(Processing::Type::Tag typeTag, const tinyxml2::XMLElement& xml) {
     LOG(VERBOSE) << __func__ << dump(xml);
     const char* typeStr = xml.Attribute("type");
-    auto aidlType = stringToProcessingType(typeTag, typeStr);
+    const char* addressStr = xml.Attribute("address");
+    // For device effect, device address is optional, match will be done for the given device type
+    // with empty address.
+    auto aidlType = stringToProcessingType(typeTag, typeStr, addressStr ? addressStr : "");
     RETURN_VALUE_IF(!aidlType.has_value(), false, "illegalStreamType");
     RETURN_VALUE_IF(0 != mProcessingMap.count(aidlType.value()), false, "duplicateStreamType");
 
diff --git a/audio/aidl/default/EffectContext.cpp b/audio/aidl/default/EffectContext.cpp
index 7b8cfb1..b354dd1 100644
--- a/audio/aidl/default/EffectContext.cpp
+++ b/audio/aidl/default/EffectContext.cpp
@@ -63,13 +63,18 @@
 }
 
 void EffectContext::dupeFmqWithReopen(IEffect::OpenEffectReturn* effectRet) {
+    const size_t inBufferSizeInFloat = mCommon.input.frameCount * mInputFrameSize / sizeof(float);
+    const size_t outBufferSizeInFloat =
+            mCommon.output.frameCount * mOutputFrameSize / sizeof(float);
+    const size_t bufferSize = std::max(inBufferSizeInFloat, outBufferSizeInFloat);
     if (!mInputMQ) {
-        mInputMQ = std::make_shared<DataMQ>(mCommon.input.frameCount * mInputFrameSize /
-                                            sizeof(float));
+        mInputMQ = std::make_shared<DataMQ>(inBufferSizeInFloat);
     }
     if (!mOutputMQ) {
-        mOutputMQ = std::make_shared<DataMQ>(mCommon.output.frameCount * mOutputFrameSize /
-                                             sizeof(float));
+        mOutputMQ = std::make_shared<DataMQ>(outBufferSizeInFloat);
+    }
+    if (mWorkBuffer.size() != bufferSize) {
+        mWorkBuffer.resize(bufferSize);
     }
     dupeFmq(effectRet);
 }
@@ -222,8 +227,6 @@
     }
 
     if (needUpdateMq) {
-        mWorkBuffer.resize(std::max(common.input.frameCount * mInputFrameSize / sizeof(float),
-                                    common.output.frameCount * mOutputFrameSize / sizeof(float)));
         return notifyDataMqUpdate();
     }
     return RetCode::SUCCESS;
@@ -242,4 +245,31 @@
     LOG(VERBOSE) << __func__ << " : signal client for reopen";
     return RetCode::SUCCESS;
 }
+
+RetCode EffectContext::enable() {
+    return RetCode::SUCCESS;
+}
+
+RetCode EffectContext::disable() {
+    return RetCode::SUCCESS;
+}
+
+RetCode EffectContext::reset() {
+    return RetCode::SUCCESS;
+}
+
+RetCode EffectContext::startDraining() {
+    mIsDraining = true;
+    return RetCode::SUCCESS;
+}
+
+RetCode EffectContext::finishDraining() {
+    mIsDraining = false;
+    return RetCode::SUCCESS;
+}
+
+bool EffectContext::isDraining() {
+    return mIsDraining;
+}
+
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/EffectImpl.cpp b/audio/aidl/default/EffectImpl.cpp
index 7192d97..97f7286 100644
--- a/audio/aidl/default/EffectImpl.cpp
+++ b/audio/aidl/default/EffectImpl.cpp
@@ -22,7 +22,10 @@
 #include "effect-impl/EffectTypes.h"
 #include "include/effect-impl/EffectTypes.h"
 
+using aidl::android::hardware::audio::effect::CommandId;
+using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kDestroyAnyStateSupportedVersion;
 using aidl::android::hardware::audio::effect::kEventFlagDataMqNotEmpty;
 using aidl::android::hardware::audio::effect::kEventFlagNotEmpty;
 using aidl::android::hardware::audio::effect::kReopenSupportedVersion;
@@ -31,13 +34,45 @@
 using ::android::hardware::EventFlag;
 
 extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
-    State state;
-    ndk::ScopedAStatus status = instanceSp->getState(&state);
-    if (!status.isOk() || State::INIT != state) {
+    if (!instanceSp) {
+        LOG(ERROR) << __func__ << " nullptr";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+
+    Descriptor desc;
+    ndk::ScopedAStatus status = instanceSp->getDescriptor(&desc);
+    if (!status.isOk()) {
         LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+                   << " failed to get descriptor, status: " << status.getDescription();
+        return EX_ILLEGAL_STATE;
+    }
+
+    State state;
+    status = instanceSp->getState(&state);
+    if (!status.isOk()) {
+        LOG(ERROR) << __func__ << " " << desc.common.name << " instance " << instanceSp.get()
                    << " in state: " << toString(state) << ", status: " << status.getDescription();
         return EX_ILLEGAL_STATE;
     }
+
+    int effectVersion = 0;
+    if (!instanceSp->getInterfaceVersion(&effectVersion).isOk()) {
+        LOG(WARNING) << __func__ << " " << desc.common.name << " failed to get interface version";
+    }
+
+    if (effectVersion < kDestroyAnyStateSupportedVersion) {
+        if (State::INIT != state) {
+            LOG(ERROR) << __func__ << " " << desc.common.name << " can not destroy instance "
+                       << instanceSp.get() << " in state: " << toString(state);
+            return EX_ILLEGAL_STATE;
+        }
+    } else {
+        instanceSp->command(CommandId::RESET);
+        instanceSp->close();
+    }
+
+    LOG(DEBUG) << __func__ << " " << desc.common.name << " instance " << instanceSp.get()
+               << " destroyed";
     return EX_NONE;
 }
 
@@ -79,7 +114,6 @@
     std::lock_guard lg(mImplMutex);
     RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "alreadyClosed");
 
-    // TODO: b/302036943 add reopen implementation
     RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext");
     mImplContext->dupeFmqWithReopen(ret);
     return ndk::ScopedAStatus::ok();
@@ -246,7 +280,6 @@
             startThread();
             break;
         case CommandId::STOP:
-        case CommandId::RESET:
             RETURN_OK_IF(mState == State::IDLE);
             mState = State::IDLE;
             RETURN_IF(notifyEventFlag(mDataMqNotEmptyEf) != RetCode::SUCCESS, EX_ILLEGAL_STATE,
@@ -254,6 +287,13 @@
             stopThread();
             RETURN_IF_ASTATUS_NOT_OK(commandImpl(command), "commandImplFailed");
             break;
+        case CommandId::RESET:
+            mState = State::IDLE;
+            RETURN_IF(notifyEventFlag(mDataMqNotEmptyEf) != RetCode::SUCCESS, EX_ILLEGAL_STATE,
+                      "notifyEventFlagNotEmptyFailed");
+            stopThread();
+            RETURN_IF_ASTATUS_NOT_OK(commandImpl(command), "commandImplFailed");
+            break;
         default:
             LOG(ERROR) << getEffectNameWithVersion() << __func__ << " instance still processing";
             return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
@@ -266,8 +306,22 @@
 
 ndk::ScopedAStatus EffectImpl::commandImpl(CommandId command) {
     RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext");
-    if (command == CommandId::RESET) {
-        mImplContext->resetBuffer();
+    switch (command) {
+        case CommandId::START:
+            mImplContext->enable();
+            break;
+        case CommandId::STOP:
+            mImplContext->disable();
+            break;
+        case CommandId::RESET:
+            mImplContext->disable();
+            mImplContext->reset();
+            mImplContext->resetBuffer();
+            break;
+        default:
+            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "commandIdNotSupported");
     }
     return ndk::ScopedAStatus::ok();
 }
@@ -327,7 +381,7 @@
 
     {
         std::lock_guard lg(mImplMutex);
-        if (mState != State::PROCESSING) {
+        if (mState != State::PROCESSING && mState != State::DRAINING) {
             LOG(DEBUG) << getEffectNameWithVersion()
                        << " skip process in state: " << toString(mState);
             return;
diff --git a/audio/aidl/default/EffectMain.cpp b/audio/aidl/default/EffectMain.cpp
index a300cfd..7a6141a 100644
--- a/audio/aidl/default/EffectMain.cpp
+++ b/audio/aidl/default/EffectMain.cpp
@@ -38,7 +38,7 @@
             candidatePath.append(apexName).append("/etc/").append(kDefaultConfigName);
             LOG(DEBUG) << __func__ << " effect lib path " << candidatePath;
             if (access(candidatePath.c_str(), R_OK) == 0) {
-                return std::move(candidatePath);
+                return candidatePath;
             }
         }
     } else {
diff --git a/audio/aidl/default/EffectThread.cpp b/audio/aidl/default/EffectThread.cpp
index b515385..1a52c13 100644
--- a/audio/aidl/default/EffectThread.cpp
+++ b/audio/aidl/default/EffectThread.cpp
@@ -68,7 +68,11 @@
 RetCode EffectThread::startThread() {
     {
         std::lock_guard lg(mThreadMutex);
-        mStop = false;
+        if (mDraining) {
+            mDraining = false;
+        } else {
+            mStop = false;
+        }
         mCv.notify_one();
     }
 
@@ -87,6 +91,25 @@
     return RetCode::SUCCESS;
 }
 
+RetCode EffectThread::startDraining() {
+    std::lock_guard lg(mThreadMutex);
+    mDraining = true;
+    mCv.notify_one();
+
+    LOG(VERBOSE) << mName << __func__;
+    return RetCode::SUCCESS;
+}
+
+RetCode EffectThread::finishDraining() {
+    std::lock_guard lg(mThreadMutex);
+    mDraining = false;
+    mStop = true;
+    mCv.notify_one();
+
+    LOG(VERBOSE) << mName << __func__;
+    return RetCode::SUCCESS;
+}
+
 void EffectThread::threadLoop() {
     pthread_setname_np(pthread_self(), mName.substr(0, kMaxTaskNameLen - 1).c_str());
     setpriority(PRIO_PROCESS, 0, mPriority);
diff --git a/audio/aidl/default/EngineConfigXmlConverter.cpp b/audio/aidl/default/EngineConfigXmlConverter.cpp
index 631cdce..d945b17 100644
--- a/audio/aidl/default/EngineConfigXmlConverter.cpp
+++ b/audio/aidl/default/EngineConfigXmlConverter.cpp
@@ -26,15 +26,19 @@
 #include <aidl/android/media/audio/common/AudioProductStrategyType.h>
 #include <android-base/logging.h>
 
+#include "core-impl/CapEngineConfigXmlConverter.h"
 #include "core-impl/EngineConfigXmlConverter.h"
 #include "core-impl/XsdcConversion.h"
 
+using aidl::android::hardware::audio::core::internal::CapEngineConfigXmlConverter;
+using aidl::android::hardware::audio::core::internal::convertAudioUsageToAidl;
 using aidl::android::media::audio::common::AudioAttributes;
 using aidl::android::media::audio::common::AudioContentType;
 using aidl::android::media::audio::common::AudioFlag;
 using aidl::android::media::audio::common::AudioHalAttributesGroup;
 using aidl::android::media::audio::common::AudioHalCapCriterion;
 using aidl::android::media::audio::common::AudioHalCapCriterionType;
+using aidl::android::media::audio::common::AudioHalCapCriterionV2;
 using aidl::android::media::audio::common::AudioHalEngineConfig;
 using aidl::android::media::audio::common::AudioHalProductStrategy;
 using aidl::android::media::audio::common::AudioHalVolumeCurve;
@@ -43,6 +47,7 @@
 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;
 
@@ -50,6 +55,10 @@
 
 namespace aidl::android::hardware::audio::core::internal {
 
+/** Default path of audio policy cap engine configuration file. */
+static constexpr char kCapEngineConfigFileName[] =
+        "/parameter-framework/Settings/Policy/PolicyConfigurableDomains.xml";
+
 void EngineConfigXmlConverter::initProductStrategyMap() {
 #define STRATEGY_ENTRY(name) {"STRATEGY_" #name, static_cast<int>(AudioProductStrategyType::name)}
 
@@ -74,6 +83,13 @@
     return it->second;
 }
 
+ConversionResult<int> EngineConfigXmlConverter::convertProductStrategyIdToAidl(int xsdcId) {
+    if (xsdcId < AudioHalProductStrategy::VENDOR_STRATEGY_ID_START) {
+        return unexpected(BAD_VALUE);
+    }
+    return xsdcId;
+}
+
 bool isDefaultAudioAttributes(const AudioAttributes& attributes) {
     return ((attributes.contentType == AudioContentType::UNKNOWN) &&
             (attributes.usage == AudioUsage::UNKNOWN) &&
@@ -95,29 +111,26 @@
     }
     AudioAttributes aidlAudioAttributes;
     if (xsdcAudioAttributes.hasContentType()) {
-        aidlAudioAttributes.contentType = static_cast<AudioContentType>(
-                xsdcAudioAttributes.getFirstContentType()->getValue());
+        aidlAudioAttributes.contentType = VALUE_OR_FATAL(convertAudioContentTypeToAidl(
+                xsdcAudioAttributes.getFirstContentType()->getValue()));
     }
     if (xsdcAudioAttributes.hasUsage()) {
-        aidlAudioAttributes.usage =
-                static_cast<AudioUsage>(xsdcAudioAttributes.getFirstUsage()->getValue());
+        aidlAudioAttributes.usage = VALUE_OR_FATAL(
+                convertAudioUsageToAidl(xsdcAudioAttributes.getFirstUsage()->getValue()));
     }
     if (xsdcAudioAttributes.hasSource()) {
-        aidlAudioAttributes.source =
-                static_cast<AudioSource>(xsdcAudioAttributes.getFirstSource()->getValue());
+        aidlAudioAttributes.source = VALUE_OR_FATAL(
+                convertAudioSourceToAidl(xsdcAudioAttributes.getFirstSource()->getValue()));
     }
     if (xsdcAudioAttributes.hasFlags()) {
         std::vector<eng_xsd::FlagType> xsdcFlagTypeVec =
                 xsdcAudioAttributes.getFirstFlags()->getValue();
-        for (const eng_xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) {
-            if (xsdcFlagType != eng_xsd::FlagType::AUDIO_FLAG_NONE) {
-                aidlAudioAttributes.flags |= 1 << (static_cast<int>(xsdcFlagType) - 1);
-            }
-        }
+        aidlAudioAttributes.flags = VALUE_OR_FATAL(convertAudioFlagsToAidl(xsdcFlagTypeVec));
     }
     if (xsdcAudioAttributes.hasBundle()) {
         const eng_xsd::BundleType* xsdcBundle = xsdcAudioAttributes.getFirstBundle();
-        aidlAudioAttributes.tags[0] = xsdcBundle->getKey() + "=" + xsdcBundle->getValue();
+        aidlAudioAttributes.tags.reserve(1);
+        aidlAudioAttributes.tags.push_back(xsdcBundle->getKey() + "_" + xsdcBundle->getValue());
     }
     if (isDefaultAudioAttributes(aidlAudioAttributes)) {
         mDefaultProductStrategyId = std::optional<int>{-1};
@@ -131,8 +144,10 @@
     static const int kStreamTypeEnumOffset =
             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.streamType = xsdcAttributesGroup.hasStreamType()
+                                             ? VALUE_OR_FATAL(convertAudioStreamTypeToAidl(
+                                                       xsdcAttributesGroup.getStreamType()))
+                                             : AudioStreamType::INVALID;
     aidlAttributesGroup.volumeGroupName = xsdcAttributesGroup.getVolumeGroup();
     if (xsdcAttributesGroup.hasAttributes_optional()) {
         aidlAttributesGroup.attributes =
@@ -164,8 +179,14 @@
         const eng_xsd::ProductStrategies::ProductStrategy& xsdcProductStrategy) {
     AudioHalProductStrategy aidlProductStrategy;
 
-    aidlProductStrategy.id =
-            VALUE_OR_FATAL(convertProductStrategyNameToAidl(xsdcProductStrategy.getName()));
+    if (xsdcProductStrategy.hasId()) {
+        aidlProductStrategy.id =
+                VALUE_OR_FATAL(convertProductStrategyIdToAidl(xsdcProductStrategy.getId()));
+    } else {
+        aidlProductStrategy.id =
+                VALUE_OR_FATAL(convertProductStrategyNameToAidl(xsdcProductStrategy.getName()));
+    }
+    aidlProductStrategy.name = xsdcProductStrategy.getName();
 
     if (xsdcProductStrategy.hasAttributesGroup()) {
         aidlProductStrategy.attributesGroups = VALUE_OR_FATAL(
@@ -247,18 +268,15 @@
     }
     if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) {
         AudioHalEngineConfig::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)));
+        capSpecificConfig.criteriaV2 =
+                std::make_optional<>(VALUE_OR_FATAL((convertCapCriteriaCollectionToAidl(
+                        getXsdcConfig()->getCriteria(), getXsdcConfig()->getCriterion_types()))));
+        internal::CapEngineConfigXmlConverter capEngConfigConverter{
+                ::android::audio_find_readable_configuration_file(kCapEngineConfigFileName)};
+        if (capEngConfigConverter.getStatus() == ::android::OK) {
+            capSpecificConfig.domains = std::move(capEngConfigConverter.getAidlCapEngineConfig());
+        }
+        mAidlEngineConfig.capSpecificConfig = capSpecificConfig;
     }
 }
 }  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 543efd1..f9fa799 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -47,6 +47,7 @@
 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::AudioGainConfig;
 using aidl::android::media::audio::common::AudioInputFlags;
 using aidl::android::media::audio::common::AudioIoFlags;
 using aidl::android::media::audio::common::AudioMMapPolicy;
@@ -183,8 +184,12 @@
     const int32_t nominalLatencyMs = getNominalLatencyMs(*portConfigIt);
     // Since this is a private method, it is assumed that
     // validity of the portConfigId has already been checked.
-    const int32_t minimumStreamBufferSizeFrames =
-            calculateBufferSizeFrames(nominalLatencyMs, portConfigIt->sampleRate.value().value);
+    int32_t minimumStreamBufferSizeFrames = 0;
+    if (!calculateBufferSizeFrames(
+                portConfigIt->format.value(), nominalLatencyMs,
+                portConfigIt->sampleRate.value().value, &minimumStreamBufferSizeFrames).isOk()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
     if (in_bufferSizeFrames < minimumStreamBufferSizeFrames) {
         LOG(ERROR) << __func__ << ": " << mType << ": insufficient buffer size "
                    << in_bufferSizeFrames << ", must be at least " << minimumStreamBufferSizeFrames;
@@ -206,9 +211,9 @@
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     const auto& flags = portConfigIt->flags.value();
-    StreamContext::DebugParameters params{mDebug.streamTransientStateDelayMs,
-                                          mVendorDebug.forceTransientBurst,
-                                          mVendorDebug.forceSynchronousDrain};
+    StreamContext::DebugParameters params{
+            mDebug.streamTransientStateDelayMs, mVendorDebug.forceTransientBurst,
+            mVendorDebug.forceSynchronousDrain, mVendorDebug.forceDrainToDraining};
     std::unique_ptr<StreamContext::DataMQ> dataMQ = nullptr;
     std::shared_ptr<IStreamCallback> streamAsyncCallback = nullptr;
     std::shared_ptr<ISoundDose> soundDose;
@@ -235,19 +240,26 @@
     return ndk::ScopedAStatus::ok();
 }
 
-std::vector<AudioDevice> Module::findConnectedDevices(int32_t portConfigId) {
+std::vector<AudioDevice> Module::getDevicesFromDevicePortConfigIds(
+        const std::set<int32_t>& devicePortConfigIds) {
     std::vector<AudioDevice> result;
-    auto& ports = getConfig().ports;
-    auto portIds = portIdsFromPortConfigIds(findConnectedPortConfigIds(portConfigId));
-    for (auto it = portIds.begin(); it != portIds.end(); ++it) {
-        auto portIt = findById<AudioPort>(ports, *it);
-        if (portIt != ports.end() && portIt->ext.getTag() == AudioPortExt::Tag::device) {
-            result.push_back(portIt->ext.template get<AudioPortExt::Tag::device>().device);
+    auto& configs = getConfig().portConfigs;
+    for (const auto& id : devicePortConfigIds) {
+        auto it = findById<AudioPortConfig>(configs, id);
+        if (it != configs.end() && it->ext.getTag() == AudioPortExt::Tag::device) {
+            result.push_back(it->ext.template get<AudioPortExt::Tag::device>().device);
+        } else {
+            LOG(FATAL) << __func__ << ": " << mType
+                       << ": failed to find device for id" << id;
         }
     }
     return result;
 }
 
+std::vector<AudioDevice> Module::findConnectedDevices(int32_t portConfigId) {
+    return getDevicesFromDevicePortConfigIds(findConnectedPortConfigIds(portConfigId));
+}
+
 std::set<int32_t> Module::findConnectedPortConfigIds(int32_t portConfigId) {
     std::set<int32_t> result;
     auto patchIdsRange = mPatches.equal_range(portConfigId);
@@ -370,6 +382,18 @@
     return kLatencyMs;
 }
 
+ndk::ScopedAStatus Module::calculateBufferSizeFrames(
+        const ::aidl::android::media::audio::common::AudioFormatDescription &format,
+        int32_t latencyMs, int32_t sampleRateHz, int32_t *bufferSizeFrames) {
+    if (format.type == AudioFormatType::PCM) {
+        *bufferSizeFrames = calculateBufferSizeFramesForPcm(latencyMs, sampleRateHz);
+        return ndk::ScopedAStatus::ok();
+    }
+    LOG(ERROR) << __func__ << ": " << mType << ": format " << format.toString()
+        << " is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
 ndk::ScopedAStatus Module::createMmapBuffer(
         const ::aidl::android::hardware::audio::core::StreamContext& context __unused,
         ::aidl::android::hardware::audio::core::StreamDescriptor* desc __unused) {
@@ -391,7 +415,7 @@
 
 Module::Configuration& Module::getConfig() {
     if (!mConfig) {
-        mConfig = std::move(initializeConfig());
+        mConfig = initializeConfig();
     }
     return *mConfig;
 }
@@ -459,58 +483,132 @@
             fillConnectionsHelper(connections, patch.sinkPortConfigIds, patch.sourcePortConfigIds);
         }  // Otherwise, there are no streams to notify.
     };
-    fillConnections(oldConnections, oldPatch);
-    fillConnections(newConnections, newPatch);
-
-    std::for_each(oldConnections.begin(), oldConnections.end(), [&](const auto& connectionPair) {
-        const int32_t mixPortConfigId = connectionPair.first;
-        if (auto it = newConnections.find(mixPortConfigId);
-            it == newConnections.end() || it->second != connectionPair.second) {
-            if (auto status = mStreams.setStreamConnectedDevices(mixPortConfigId, {});
-                status.isOk()) {
-                LOG(DEBUG) << "updateStreamsConnectedState: The stream on port config id "
-                           << mixPortConfigId << " has been disconnected";
-            } else {
-                // Disconnection is tricky to roll back, just register a failure.
-                maybeFailure = std::move(status);
+    auto restoreOldConnections = [&](const std::set<int32_t>& mixPortIds,
+                                     const bool continueWithEmptyDevices) {
+        for (const auto mixPort : mixPortIds) {
+            if (auto it = oldConnections.find(mixPort);
+                continueWithEmptyDevices || it != oldConnections.end()) {
+                const std::vector<AudioDevice> d =
+                        it != oldConnections.end() ? getDevicesFromDevicePortConfigIds(it->second)
+                                                   : std::vector<AudioDevice>();
+                if (auto status = mStreams.setStreamConnectedDevices(mixPort, d); status.isOk()) {
+                    LOG(WARNING) << ":updateStreamsConnectedState: rollback: mix port config:"
+                                 << mixPort
+                                 << (d.empty() ? "; not connected"
+                                               : std::string("; connected to ") +
+                                                         ::android::internal::ToString(d));
+                } else {
+                    // can't do much about rollback failures
+                    LOG(ERROR)
+                            << ":updateStreamsConnectedState: rollback: failed for mix port config:"
+                            << mixPort;
+                }
             }
         }
-    });
-    if (!maybeFailure.isOk()) return maybeFailure;
-    std::set<int32_t> idsToDisconnectOnFailure;
-    std::for_each(newConnections.begin(), newConnections.end(), [&](const auto& connectionPair) {
-        const int32_t mixPortConfigId = connectionPair.first;
-        if (auto it = oldConnections.find(mixPortConfigId);
-            it == oldConnections.end() || it->second != connectionPair.second) {
-            const auto connectedDevices = findConnectedDevices(mixPortConfigId);
+    };
+    fillConnections(oldConnections, oldPatch);
+    fillConnections(newConnections, newPatch);
+    /**
+     * Illustration of oldConnections and newConnections
+     *
+     * oldConnections {
+     * a : {A,B,C},
+     * b : {D},
+     * d : {H,I,J},
+     * e : {N,O,P},
+     * f : {Q,R},
+     * g : {T,U,V},
+     * }
+     *
+     * newConnections {
+     * a : {A,B,C},
+     * c : {E,F,G},
+     * d : {K,L,M},
+     * e : {N,P},
+     * f : {Q,R,S},
+     * g : {U,V,W},
+     * }
+     *
+     * Expected routings:
+     *      'a': is ignored both in disconnect step and connect step,
+     *           due to same devices both in oldConnections and newConnections.
+     *      'b': handled only in disconnect step with empty devices because 'b' is only present
+     *           in oldConnections.
+     *      'c': handled only in connect step with {E,F,G} devices because 'c' is only present
+     *           in newConnections.
+     *      'd': handled only in connect step with {K,L,M} devices because 'd' is also present
+     *           in newConnections and it is ignored in disconnected step.
+     *      'e': handled only in connect step with {N,P} devices because 'e' is also present
+     *           in newConnections and it is ignored in disconnect step. please note that there
+     *           is no exclusive disconnection for device {O}.
+     *      'f': handled only in connect step with {Q,R,S} devices because 'f' is also present
+     *           in newConnections and it is ignored in disconnect step. Even though stream is
+     *           already connected with {Q,R} devices and connection happens with {Q,R,S}.
+     *      'g': handled only in connect step with {U,V,W} devices because 'g' is also present
+     *           in newConnections and it is ignored in disconnect step. There is no exclusive
+     *           disconnection with devices {T,U,V}.
+     *
+     *       If, any failure, will lead to restoreOldConnections (rollback).
+     *       The aim of the restoreOldConnections is to make connections back to oldConnections.
+     *       Failures in restoreOldConnections aren't handled.
+     */
+
+    std::set<int32_t> idsToConnectBackOnFailure;
+    // disconnection step
+    for (const auto& [oldMixPortConfigId, oldDevicePortConfigIds] : oldConnections) {
+        if (auto it = newConnections.find(oldMixPortConfigId); it == newConnections.end()) {
+            idsToConnectBackOnFailure.insert(oldMixPortConfigId);
+            if (auto status = mStreams.setStreamConnectedDevices(oldMixPortConfigId, {});
+                status.isOk()) {
+                LOG(DEBUG) << __func__ << ": The stream on port config id " << oldMixPortConfigId
+                           << " has been disconnected";
+            } else {
+                maybeFailure = std::move(status);
+                // proceed to rollback even on one failure
+                break;
+            }
+        }
+    }
+
+    if (!maybeFailure.isOk()) {
+        restoreOldConnections(idsToConnectBackOnFailure, false /*continueWithEmptyDevices*/);
+        LOG(WARNING) << __func__ << ": failed to disconnect from old patch. attempted rollback";
+        return maybeFailure;
+    }
+
+    std::set<int32_t> idsToRollbackOnFailure;
+    // connection step
+    for (const auto& [newMixPortConfigId, newDevicePortConfigIds] : newConnections) {
+        if (auto it = oldConnections.find(newMixPortConfigId);
+            it == oldConnections.end() || it->second != newDevicePortConfigIds) {
+            const auto connectedDevices = getDevicesFromDevicePortConfigIds(newDevicePortConfigIds);
+            idsToRollbackOnFailure.insert(newMixPortConfigId);
             if (connectedDevices.empty()) {
                 // This is important as workers use the vector size to derive the connection status.
-                LOG(FATAL) << "updateStreamsConnectedState: No connected devices found for port "
-                              "config id "
-                           << mixPortConfigId;
+                LOG(FATAL) << __func__ << ": No connected devices found for port config id "
+                           << newMixPortConfigId;
             }
-            if (auto status = mStreams.setStreamConnectedDevices(mixPortConfigId, connectedDevices);
+            if (auto status =
+                        mStreams.setStreamConnectedDevices(newMixPortConfigId, connectedDevices);
                 status.isOk()) {
-                LOG(DEBUG) << "updateStreamsConnectedState: The stream on port config id "
-                           << mixPortConfigId << " has been connected to: "
+                LOG(DEBUG) << __func__ << ": The stream on port config id " << newMixPortConfigId
+                           << " has been connected to: "
                            << ::android::internal::ToString(connectedDevices);
             } else {
                 maybeFailure = std::move(status);
-                idsToDisconnectOnFailure.insert(mixPortConfigId);
+                // proceed to rollback even on one failure
+                break;
             }
         }
-    });
+    }
+
     if (!maybeFailure.isOk()) {
-        LOG(WARNING) << __func__ << ": " << mType
-                     << ": Due to a failure, disconnecting streams on port config ids "
-                     << ::android::internal::ToString(idsToDisconnectOnFailure);
-        std::for_each(idsToDisconnectOnFailure.begin(), idsToDisconnectOnFailure.end(),
-                      [&](const auto& portConfigId) {
-                          auto status = mStreams.setStreamConnectedDevices(portConfigId, {});
-                          (void)status.isOk();  // Can't do much about a failure here.
-                      });
+        restoreOldConnections(idsToConnectBackOnFailure, false /*continueWithEmptyDevices*/);
+        restoreOldConnections(idsToRollbackOnFailure, true /*continueWithEmptyDevices*/);
+        LOG(WARNING) << __func__ << ": failed to connect for new patch. attempted rollback";
         return maybeFailure;
     }
+
     return ndk::ScopedAStatus::ok();
 }
 
@@ -1041,8 +1139,14 @@
     *_aidl_return = in_requested;
     auto maxSampleRateIt = std::max_element(sampleRates.begin(), sampleRates.end());
     const int32_t latencyMs = getNominalLatencyMs(*(maxSampleRateIt->second));
-    _aidl_return->minimumStreamBufferSizeFrames =
-            calculateBufferSizeFrames(latencyMs, maxSampleRateIt->first);
+    if (!calculateBufferSizeFrames(
+                maxSampleRateIt->second->format.value(), latencyMs, maxSampleRateIt->first,
+                &_aidl_return->minimumStreamBufferSizeFrames).isOk()) {
+        if (patchesBackup.has_value()) {
+            mPatches = std::move(*patchesBackup);
+        }
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
     _aidl_return->latenciesMs.clear();
     _aidl_return->latenciesMs.insert(_aidl_return->latenciesMs.end(),
                                      _aidl_return->sinkPortConfigIds.size(), latencyMs);
@@ -1200,7 +1304,9 @@
     }
 
     if (in_requested.gain.has_value()) {
-        // Let's pretend that gain can always be applied.
+        if (!setAudioPortConfigGain(*portIt, in_requested.gain.value())) {
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
         out_suggested->gain = in_requested.gain.value();
     }
 
@@ -1242,6 +1348,52 @@
     return ndk::ScopedAStatus::ok();
 }
 
+bool Module::setAudioPortConfigGain(const AudioPort& port, const AudioGainConfig& gainRequested) {
+    auto& ports = getConfig().ports;
+    if (gainRequested.index < 0 || gainRequested.index >= (int)port.gains.size()) {
+        LOG(ERROR) << __func__ << ": gains for port " << port.id << " is undefined";
+        return false;
+    }
+    int stepValue = port.gains[gainRequested.index].stepValue;
+    if (stepValue == 0) {
+        LOG(ERROR) << __func__ << ": port gain step value is 0";
+        return false;
+    }
+    int minValue = port.gains[gainRequested.index].minValue;
+    int maxValue = port.gains[gainRequested.index].maxValue;
+    if (gainRequested.values[0] > maxValue || gainRequested.values[0] < minValue) {
+        LOG(ERROR) << __func__ << ": gain value " << gainRequested.values[0]
+                   << " out of range of min and max gain config";
+        return false;
+    }
+    int gainIndex = (gainRequested.values[0] - minValue) / stepValue;
+    int totalSteps = (maxValue - minValue) / stepValue;
+    if (totalSteps == 0) {
+        LOG(ERROR) << __func__ << ": difference between port gain min value " << minValue
+                   << " and max value " << maxValue << " is less than step value " << stepValue;
+        return false;
+    }
+    // Root-power quantities are used in curve:
+    // 10^((minMb / 100 + (maxMb / 100 - minMb / 100) * gainIndex / totalSteps) / (10 * 2))
+    // where 100 is the conversion from mB to dB, 10 comes from the log 10 conversion from power
+    // ratios, and 2 means are the square of amplitude.
+    float gain =
+            pow(10, (minValue + (maxValue - minValue) * (gainIndex / (float)totalSteps)) / 2000);
+    if (gain < 0) {
+        LOG(ERROR) << __func__ << ": gain " << gain << " is less than 0";
+        return false;
+    }
+    for (const auto& route : getConfig().routes) {
+        if (route.sinkPortId != port.id) {
+            continue;
+        }
+        for (const auto sourcePortId : route.sourcePortIds) {
+            mStreams.setGain(sourcePortId, gain);
+        }
+    }
+    return true;
+}
+
 ndk::ScopedAStatus Module::resetAudioPatch(int32_t in_patchId) {
     auto& patches = getConfig().patches;
     auto patchIt = findById<AudioPatch>(patches, in_patchId);
@@ -1394,6 +1546,7 @@
 
 const std::string Module::VendorDebug::kForceTransientBurstName = "aosp.forceTransientBurst";
 const std::string Module::VendorDebug::kForceSynchronousDrainName = "aosp.forceSynchronousDrain";
+const std::string Module::VendorDebug::kForceDrainToDrainingName = "aosp.forceDrainToDraining";
 
 ndk::ScopedAStatus Module::getVendorParameters(const std::vector<std::string>& in_ids,
                                                std::vector<VendorParameter>* _aidl_return) {
@@ -1408,6 +1561,10 @@
             VendorParameter forceSynchronousDrain{.id = id};
             forceSynchronousDrain.ext.setParcelable(Boolean{mVendorDebug.forceSynchronousDrain});
             _aidl_return->push_back(std::move(forceSynchronousDrain));
+        } else if (id == VendorDebug::kForceDrainToDrainingName) {
+            VendorParameter forceDrainToDraining{.id = id};
+            forceDrainToDraining.ext.setParcelable(Boolean{mVendorDebug.forceDrainToDraining});
+            _aidl_return->push_back(std::move(forceDrainToDraining));
         } else {
             allParametersKnown = false;
             LOG(VERBOSE) << __func__ << ": " << mType << ": unrecognized parameter \"" << id << "\"";
@@ -1448,6 +1605,10 @@
             if (!extractParameter<Boolean>(p, &mVendorDebug.forceSynchronousDrain)) {
                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
             }
+        } else if (p.id == VendorDebug::kForceDrainToDrainingName) {
+            if (!extractParameter<Boolean>(p, &mVendorDebug.forceDrainToDraining)) {
+                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+            }
         } else {
             allParametersKnown = false;
             LOG(VERBOSE) << __func__ << ": " << mType << ": unrecognized parameter \"" << p.id
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index eecc972..4525f6a 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -47,6 +47,17 @@
 
 namespace aidl::android::hardware::audio::core {
 
+namespace {
+
+template <typename MQTypeError>
+auto fmqErrorHandler(const char* mqName) {
+    return [m = std::string(mqName)](MQTypeError fmqError, std::string&& errorMessage) {
+        CHECK_EQ(fmqError, MQTypeError::NONE) << m << ": " << errorMessage;
+    };
+}
+
+}  // namespace
+
 void StreamContext::fillDescriptor(StreamDescriptor* desc) {
     if (mCommandMQ) {
         desc->command = mCommandMQ->dupeDesc();
@@ -332,11 +343,7 @@
 bool StreamInWorkerLogic::read(size_t clientSize, StreamDescriptor::Reply* reply) {
     ATRACE_CALL();
     StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
-    StreamContext::DataMQ::Error fmqError = StreamContext::DataMQ::Error::NONE;
-    std::string fmqErrorMsg;
-    const size_t byteCount = std::min(
-            {clientSize, dataMQ->availableToWrite(&fmqError, &fmqErrorMsg), mDataBufferSize});
-    CHECK(fmqError == StreamContext::DataMQ::Error::NONE) << fmqErrorMsg;
+    const size_t byteCount = std::min({clientSize, dataMQ->availableToWrite(), mDataBufferSize});
     const bool isConnected = mIsConnected;
     const size_t frameSize = mContext->getFrameSize();
     size_t actualFrameCount = 0;
@@ -375,8 +382,20 @@
 const std::string StreamOutWorkerLogic::kThreadName = "writer";
 
 StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
-    if (mState == StreamDescriptor::State::DRAINING ||
-        mState == StreamDescriptor::State::TRANSFERRING) {
+    if (mState == StreamDescriptor::State::DRAINING && mContext->getForceDrainToDraining() &&
+        mOnDrainReadyStatus == OnDrainReadyStatus::UNSENT) {
+        std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
+        if (asyncCallback != nullptr) {
+            ndk::ScopedAStatus status = asyncCallback->onDrainReady();
+            if (!status.isOk()) {
+                LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
+            }
+            // This sets the timeout for moving into IDLE on next iterations.
+            switchToTransientState(StreamDescriptor::State::DRAINING);
+            mOnDrainReadyStatus = OnDrainReadyStatus::SENT;
+        }
+    } else if (mState == StreamDescriptor::State::DRAINING ||
+               mState == StreamDescriptor::State::TRANSFERRING) {
         if (auto stateDurationMs = std::chrono::duration_cast<std::chrono::milliseconds>(
                     std::chrono::steady_clock::now() - mTransientStateStart);
             stateDurationMs >= mTransientStateDelayMs) {
@@ -389,9 +408,12 @@
                 // drain or transfer completion. In the stub, we switch unconditionally.
                 if (mState == StreamDescriptor::State::DRAINING) {
                     mState = StreamDescriptor::State::IDLE;
-                    ndk::ScopedAStatus status = asyncCallback->onDrainReady();
-                    if (!status.isOk()) {
-                        LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
+                    if (mOnDrainReadyStatus != OnDrainReadyStatus::SENT) {
+                        ndk::ScopedAStatus status = asyncCallback->onDrainReady();
+                        if (!status.isOk()) {
+                            LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
+                        }
+                        mOnDrainReadyStatus = OnDrainReadyStatus::SENT;
                     }
                 } else {
                     mState = StreamDescriptor::State::ACTIVE;
@@ -530,6 +552,10 @@
                             mState = StreamDescriptor::State::IDLE;
                         } else {
                             switchToTransientState(StreamDescriptor::State::DRAINING);
+                            mOnDrainReadyStatus =
+                                    mode == StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY
+                                            ? OnDrainReadyStatus::UNSENT
+                                            : OnDrainReadyStatus::IGNORE;
                         }
                     } else {
                         LOG(ERROR) << __func__ << ": drain failed: " << status;
@@ -612,10 +638,7 @@
 bool StreamOutWorkerLogic::write(size_t clientSize, StreamDescriptor::Reply* reply) {
     ATRACE_CALL();
     StreamContext::DataMQ* const dataMQ = mContext->getDataMQ();
-    StreamContext::DataMQ::Error fmqError = StreamContext::DataMQ::Error::NONE;
-    std::string fmqErrorMsg;
-    const size_t readByteCount = dataMQ->availableToRead(&fmqError, &fmqErrorMsg);
-    CHECK(fmqError == StreamContext::DataMQ::Error::NONE) << fmqErrorMsg;
+    const size_t readByteCount = dataMQ->availableToRead();
     const size_t frameSize = mContext->getFrameSize();
     bool fatal = false;
     int32_t latency = mContext->getNominalLatencyMs();
@@ -719,6 +742,14 @@
             LOG(WARNING) << __func__ << ": invalid worker tid: " << workerTid;
         }
     }
+    getContext().getCommandMQ()->setErrorHandler(
+            fmqErrorHandler<StreamContext::CommandMQ::Error>("CommandMQ"));
+    getContext().getReplyMQ()->setErrorHandler(
+            fmqErrorHandler<StreamContext::ReplyMQ::Error>("ReplyMQ"));
+    if (getContext().getDataMQ() != nullptr) {
+        getContext().getDataMQ()->setErrorHandler(
+                fmqErrorHandler<StreamContext::DataMQ::Error>("DataMQ"));
+    }
     return ndk::ScopedAStatus::ok();
 }
 
@@ -843,6 +874,11 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus StreamCommonImpl::setGain(float gain) {
+    LOG(DEBUG) << __func__ << ": gain " << gain;
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
 ndk::ScopedAStatus StreamCommonImpl::bluetoothParametersUpdated() {
     LOG(DEBUG) << __func__;
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@@ -920,9 +956,12 @@
 }
 
 StreamInHwGainHelper::StreamInHwGainHelper(const StreamContext* context)
-    : mChannelCount(getChannelCount(context->getChannelLayout())), mHwGains(mChannelCount, 0.0f) {}
+    : mChannelCount(getChannelCount(context->getChannelLayout())) {}
 
 ndk::ScopedAStatus StreamInHwGainHelper::getHwGainImpl(std::vector<float>* _aidl_return) {
+    if (mHwGains.empty()) {
+        mHwGains.resize(mChannelCount, 0.0f);
+    }
     *_aidl_return = mHwGains;
     LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
     return ndk::ScopedAStatus::ok();
@@ -1051,10 +1090,12 @@
 }
 
 StreamOutHwVolumeHelper::StreamOutHwVolumeHelper(const StreamContext* context)
-    : mChannelCount(getChannelCount(context->getChannelLayout())),
-      mHwVolumes(mChannelCount, 0.0f) {}
+    : mChannelCount(getChannelCount(context->getChannelLayout())) {}
 
 ndk::ScopedAStatus StreamOutHwVolumeHelper::getHwVolumeImpl(std::vector<float>* _aidl_return) {
+    if (mHwVolumes.empty()) {
+        mHwVolumes.resize(mChannelCount, 0.0f);
+    }
     *_aidl_return = mHwVolumes;
     LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
     return ndk::ScopedAStatus::ok();
diff --git a/audio/aidl/default/XsdcConversion.cpp b/audio/aidl/default/XsdcConversion.cpp
index 1720949..b42d7f5 100644
--- a/audio/aidl/default/XsdcConversion.cpp
+++ b/audio/aidl/default/XsdcConversion.cpp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2024 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 <inttypes.h>
 
 #include <unordered_set>
@@ -5,16 +21,25 @@
 #define LOG_TAG "AHAL_Config"
 #include <android-base/logging.h>
 #include <android-base/strings.h>
+#include <android/binder_enums.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 <media/convert.h>
+#include <utils/FastStrcmp.h>
+
+#include <Utils.h>
 
 #include "core-impl/XmlConverter.h"
 #include "core-impl/XsdcConversion.h"
 
+using aidl::android::hardware::audio::common::iequals;
+using aidl::android::hardware::audio::common::isValidAudioMode;
+using aidl::android::hardware::audio::common::kValidAudioModes;
 using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioContentType;
 using aidl::android::media::audio::common::AudioDevice;
 using aidl::android::media::audio::common::AudioDeviceAddress;
 using aidl::android::media::audio::common::AudioDeviceDescription;
@@ -24,22 +49,39 @@
 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::AudioHalCapCriterionV2;
 using aidl::android::media::audio::common::AudioHalVolumeCurve;
 using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioMode;
+using aidl::android::media::audio::common::AudioPolicyForceUse;
 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;
+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;
+using android::utilities::convertTo;
+using ndk::enum_range;
 
 namespace ap_xsd = android::audio::policy::configuration;
 namespace eng_xsd = android::audio::policy::engine::configuration;
 
 namespace aidl::android::hardware::audio::core::internal {
 
+static constexpr const char kXsdcForceConfigForCommunication[] = "ForceUseForCommunication";
+static constexpr const char kXsdcForceConfigForMedia[] = "ForceUseForMedia";
+static constexpr const char kXsdcForceConfigForRecord[] = "ForceUseForRecord";
+static constexpr const char kXsdcForceConfigForDock[] = "ForceUseForDock";
+static constexpr const char kXsdcForceConfigForSystem[] = "ForceUseForSystem";
+static constexpr const char kXsdcForceConfigForHdmiSystemAudio[] = "ForceUseForHdmiSystemAudio";
+static constexpr const char kXsdcForceConfigForEncodedSurround[] = "ForceUseForEncodedSurround";
+static constexpr const char kXsdcForceConfigForVibrateRinging[] = "ForceUseForVibrateRinging";
+
 inline ConversionResult<std::string> assertNonEmpty(const std::string& s) {
     if (s.empty()) {
         LOG(ERROR) << __func__ << " Review Audio Policy config: "
@@ -51,6 +93,100 @@
 
 #define NON_EMPTY_STRING_OR_FATAL(s) VALUE_OR_FATAL(assertNonEmpty(s))
 
+ConversionResult<int32_t> convertAudioFlagsToAidl(
+        const std::vector<eng_xsd::FlagType>& xsdcFlagTypeVec) {
+    int legacyFlagMask = 0;
+    for (const eng_xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) {
+        if (xsdcFlagType != eng_xsd::FlagType::AUDIO_FLAG_NONE) {
+            audio_flags_mask_t legacyFlag = AUDIO_FLAG_NONE;
+            if (!::android::AudioFlagConverter::fromString(eng_xsd::toString(xsdcFlagType),
+                                                           legacyFlag)) {
+                LOG(ERROR) << __func__ << " Review Audio Policy config, "
+                           << eng_xsd::toString(xsdcFlagType) << " is not a valid flag.";
+                return unexpected(BAD_VALUE);
+            }
+            legacyFlagMask |= static_cast<int>(legacyFlag);
+        }
+    }
+    ConversionResult<int32_t> result = legacy2aidl_audio_flags_mask_t_int32_t_mask(
+            static_cast<audio_flags_mask_t>(legacyFlagMask));
+    if (!result.ok()) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyFlagMask
+                   << " has invalid flag(s).";
+        return unexpected(BAD_VALUE);
+    }
+    return result;
+}
+
+ConversionResult<AudioStreamType> convertAudioStreamTypeToAidl(const eng_xsd::Stream& xsdcStream) {
+    audio_stream_type_t legacyStreamType;
+    if (!::android::StreamTypeConverter::fromString(eng_xsd::toString(xsdcStream),
+                                                    legacyStreamType)) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config, " << eng_xsd::toString(xsdcStream)
+                   << " is not a valid audio stream type.";
+        return unexpected(BAD_VALUE);
+    }
+    ConversionResult<AudioStreamType> result =
+            legacy2aidl_audio_stream_type_t_AudioStreamType(legacyStreamType);
+    if (!result.ok()) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyStreamType
+                   << " is not a valid audio stream type.";
+        return unexpected(BAD_VALUE);
+    }
+    return result;
+}
+
+ConversionResult<AudioSource> convertAudioSourceToAidl(
+        const eng_xsd::SourceEnumType& xsdcSourceType) {
+    audio_source_t legacySourceType;
+    if (!::android::SourceTypeConverter::fromString(eng_xsd::toString(xsdcSourceType),
+                                                    legacySourceType)) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config, "
+                   << eng_xsd::toString(xsdcSourceType) << " is not a valid audio source.";
+        return unexpected(BAD_VALUE);
+    }
+    ConversionResult<AudioSource> result = legacy2aidl_audio_source_t_AudioSource(legacySourceType);
+    if (!result.ok()) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacySourceType
+                   << " is not a valid audio source.";
+        return unexpected(BAD_VALUE);
+    }
+    return result;
+}
+
+ConversionResult<AudioContentType> convertAudioContentTypeToAidl(
+        const eng_xsd::ContentType& xsdcContentType) {
+    audio_content_type_t legacyContentType;
+    if (!::android::AudioContentTypeConverter::fromString(eng_xsd::toString(xsdcContentType),
+                                                          legacyContentType)) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config, "
+                   << eng_xsd::toString(xsdcContentType) << " is not a valid audio content type.";
+        return unexpected(BAD_VALUE);
+    }
+    ConversionResult<AudioContentType> result =
+            legacy2aidl_audio_content_type_t_AudioContentType(legacyContentType);
+    if (!result.ok()) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyContentType
+                   << " is not a valid audio content type.";
+        return unexpected(BAD_VALUE);
+    }
+    return result;
+}
+
+ConversionResult<AudioUsage> convertAudioUsageToAidl(const eng_xsd::UsageEnumType& xsdcUsage) {
+    audio_usage_t legacyUsage;
+    if (!::android::UsageTypeConverter::fromString(eng_xsd::toString(xsdcUsage), legacyUsage)) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config, not a valid audio usage.";
+        return unexpected(BAD_VALUE);
+    }
+    ConversionResult<AudioUsage> result = legacy2aidl_audio_usage_t_AudioUsage(legacyUsage);
+    if (!result.ok()) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config, not a valid audio usage.";
+        return unexpected(BAD_VALUE);
+    }
+    return result;
+}
+
 ConversionResult<AudioFormatDescription> convertAudioFormatToAidl(const std::string& xsdcFormat) {
     audio_format_t legacyFormat = ::android::formatFromString(xsdcFormat, AUDIO_FORMAT_DEFAULT);
     ConversionResult<AudioFormatDescription> result =
@@ -410,32 +546,263 @@
     return result;
 }
 
+ConversionResult<AudioMode> convertTelephonyModeToAidl(const std::string& xsdcModeCriterionType) {
+    const auto it = std::find_if(kValidAudioModes.begin(), kValidAudioModes.end(),
+                                 [&xsdcModeCriterionType](const auto& mode) {
+                                     return toString(mode) == xsdcModeCriterionType;
+                                 });
+    if (it == kValidAudioModes.end()) {
+        LOG(ERROR) << __func__ << " invalid mode " << xsdcModeCriterionType;
+        return unexpected(BAD_VALUE);
+    }
+    return *it;
+}
+
+ConversionResult<AudioDeviceAddress> convertDeviceAddressToAidl(const std::string& xsdcAddress) {
+    return AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(xsdcAddress);
+}
+
+ConversionResult<eng_xsd::CriterionTypeType> getCriterionTypeByName(
+        const std::string& name,
+        const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
+    for (const auto& xsdCriterionTypes : xsdcCriterionTypesVec) {
+        for (const auto& xsdcCriterionType : xsdCriterionTypes.getCriterion_type()) {
+            if (xsdcCriterionType.getName() == name) {
+                return xsdcCriterionType;
+            }
+        }
+    }
+    LOG(ERROR) << __func__ << " failed to find criterion type " << name;
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<std::vector<std::optional<AudioHalCapCriterionV2>>>
+convertCapCriteriaCollectionToAidl(
+        const std::vector<eng_xsd::CriteriaType>& xsdcCriteriaVec,
+        const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
+    std::vector<std::optional<AudioHalCapCriterionV2>> resultAidlCriterionVec;
+    if (xsdcCriteriaVec.empty() || xsdcCriterionTypesVec.empty()) {
+        LOG(ERROR) << __func__ << " empty criteria/criterionTypes";
+        return unexpected(BAD_VALUE);
+    }
+    for (const auto& xsdCriteria : xsdcCriteriaVec) {
+        for (const auto& xsdcCriterion : xsdCriteria.getCriterion()) {
+            resultAidlCriterionVec.push_back(
+                    std::optional<AudioHalCapCriterionV2>(VALUE_OR_FATAL(
+                            convertCapCriterionV2ToAidl(xsdcCriterion, xsdcCriterionTypesVec))));
+        }
+    }
+    return resultAidlCriterionVec;
+}
+
+ConversionResult<std::vector<AudioDeviceDescription>> convertDevicesToAidl(
+        const eng_xsd::CriterionTypeType& xsdcDeviceCriterionType) {
+    if (xsdcDeviceCriterionType.getValues().empty()) {
+        LOG(ERROR) << __func__ << " no values provided";
+        return unexpected(BAD_VALUE);
+    }
+    std::vector<AudioDeviceDescription> aidlDevices;
+    for (eng_xsd::ValuesType xsdcValues : xsdcDeviceCriterionType.getValues()) {
+        aidlDevices.reserve(xsdcValues.getValue().size());
+        for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
+            if (!xsdcValue.hasAndroid_type()) {
+                LOG(ERROR) << __func__ << " empty android type";
+                return unexpected(BAD_VALUE);
+            }
+            uint32_t integerValue;
+            if (!convertTo(xsdcValue.getAndroid_type(), integerValue)) {
+                LOG(ERROR) << __func__ << " failed to convert android type "
+                           << xsdcValue.getAndroid_type();
+                return unexpected(BAD_VALUE);
+            }
+            aidlDevices.push_back(
+                    VALUE_OR_RETURN(legacy2aidl_audio_devices_t_AudioDeviceDescription(
+                            static_cast<audio_devices_t>(integerValue))));
+        }
+    }
+    return aidlDevices;
+}
+
+ConversionResult<std::vector<AudioDeviceAddress>> convertDeviceAddressesToAidl(
+        const eng_xsd::CriterionTypeType& xsdcDeviceAddressesCriterionType) {
+    if (xsdcDeviceAddressesCriterionType.getValues().empty()) {
+        LOG(ERROR) << __func__ << " no values provided";
+        return unexpected(BAD_VALUE);
+    }
+    std::vector<AudioDeviceAddress> aidlDeviceAddresses;
+    for (eng_xsd::ValuesType xsdcValues : xsdcDeviceAddressesCriterionType.getValues()) {
+        aidlDeviceAddresses.reserve(xsdcValues.getValue().size());
+        for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
+            aidlDeviceAddresses.push_back(
+                    AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(xsdcValue.getLiteral()));
+        }
+    }
+    return aidlDeviceAddresses;
+}
+
+ConversionResult<AudioMode> convertAudioModeToAidl(const std::string& xsdcAudioModeType) {
+    const auto it = std::find_if(enum_range<AudioMode>().begin(), enum_range<AudioMode>().end(),
+                                 [&](const auto v) { return toString(v) == xsdcAudioModeType; });
+    if (it == enum_range<AudioMode>().end()) {
+        LOG(ERROR) << __func__ << " invalid audio mode " << xsdcAudioModeType;
+        return unexpected(BAD_VALUE);
+    }
+    return *it;
+}
+
+ConversionResult<std::vector<AudioMode>> convertTelephonyModesToAidl(
+        const eng_xsd::CriterionTypeType& xsdcTelephonyModeCriterionType) {
+    if (xsdcTelephonyModeCriterionType.getValues().empty()) {
+        LOG(ERROR) << __func__ << " no values provided";
+        return unexpected(BAD_VALUE);
+    }
+    std::vector<AudioMode> aidlAudioModes;
+    for (eng_xsd::ValuesType xsdcValues : xsdcTelephonyModeCriterionType.getValues()) {
+        aidlAudioModes.reserve(xsdcValues.getValue().size());
+        for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
+            aidlAudioModes.push_back(
+                    VALUE_OR_RETURN(convertAudioModeToAidl(xsdcValue.getLiteral())));
+        }
+    }
+    return aidlAudioModes;
+}
+
+ConversionResult<std::vector<AudioPolicyForceUse>> convertForceUseConfigsToAidl(
+        const std::string& criterionValue,
+        const eng_xsd::CriterionTypeType& xsdcForcedConfigCriterionType) {
+    if (xsdcForcedConfigCriterionType.getValues().empty()) {
+        LOG(ERROR) << __func__ << " no values provided";
+        return unexpected(BAD_VALUE);
+    }
+    std::vector<AudioPolicyForceUse> aidlForcedConfigs;
+    for (eng_xsd::ValuesType xsdcValues : xsdcForcedConfigCriterionType.getValues()) {
+        aidlForcedConfigs.reserve(xsdcValues.getValue().size());
+        for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
+            aidlForcedConfigs.push_back(
+                    VALUE_OR_RETURN(convertForceUseToAidl(criterionValue, xsdcValue.getLiteral())));
+        }
+    }
+    return aidlForcedConfigs;
+}
+
+template <typename T>
+ConversionResult<T> convertForceUseForcedConfigToAidl(
+        const std::string& xsdcForcedConfigCriterionType) {
+    const auto it = std::find_if(enum_range<T>().begin(), enum_range<T>().end(), [&](const auto v) {
+        return toString(v) == xsdcForcedConfigCriterionType;
+    });
+    if (it == enum_range<T>().end()) {
+        LOG(ERROR) << __func__ << " invalid forced config " << xsdcForcedConfigCriterionType;
+        return unexpected(BAD_VALUE);
+    }
+    return *it;
+}
+
+ConversionResult<AudioPolicyForceUse> convertForceUseToAidl(const std::string& xsdcCriterionName,
+                                                            const std::string& xsdcCriterionValue) {
+    if (!fastcmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForCommunication,
+                          strlen(kXsdcForceConfigForCommunication))) {
+        const auto deviceCategory = VALUE_OR_RETURN(
+                convertForceUseForcedConfigToAidl<AudioPolicyForceUse::CommunicationDeviceCategory>(
+                        xsdcCriterionValue));
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::forCommunication>(deviceCategory);
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForMedia,
+            strlen(kXsdcForceConfigForMedia))) {
+        const auto deviceCategory = VALUE_OR_RETURN(
+                convertForceUseForcedConfigToAidl<AudioPolicyForceUse::MediaDeviceCategory>(
+                        xsdcCriterionValue));
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::forMedia>(deviceCategory);
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForRecord,
+            strlen(kXsdcForceConfigForRecord))) {
+        const auto deviceCategory = VALUE_OR_RETURN(
+                convertForceUseForcedConfigToAidl<AudioPolicyForceUse::CommunicationDeviceCategory>(
+                        xsdcCriterionValue));
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::forRecord>(deviceCategory);
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForDock,
+                           strlen(kXsdcForceConfigForDock))) {
+        const auto dockType =
+                VALUE_OR_RETURN(convertForceUseForcedConfigToAidl<AudioPolicyForceUse::DockType>(
+                        xsdcCriterionValue));
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::dock>(dockType);
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForSystem,
+            strlen(kXsdcForceConfigForSystem))) {
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::systemSounds>(xsdcCriterionValue ==
+                                                                            "SYSTEM_ENFORCED");
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForHdmiSystemAudio,
+            strlen(kXsdcForceConfigForHdmiSystemAudio))) {
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::hdmiSystemAudio>(
+                xsdcCriterionValue == "HDMI_SYSTEM_AUDIO_ENFORCED");
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForEncodedSurround,
+            strlen(kXsdcForceConfigForEncodedSurround))) {
+        const auto encodedSurround = VALUE_OR_RETURN(
+                convertForceUseForcedConfigToAidl<AudioPolicyForceUse::EncodedSurroundConfig>(
+                        xsdcCriterionValue));
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::encodedSurround>(encodedSurround);
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForVibrateRinging,
+            strlen(kXsdcForceConfigForVibrateRinging))) {
+        const auto deviceCategory = VALUE_OR_RETURN(
+                convertForceUseForcedConfigToAidl<AudioPolicyForceUse::CommunicationDeviceCategory>(
+                        xsdcCriterionValue));
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::forVibrateRinging>(deviceCategory);
+    }
+    LOG(ERROR) << __func__ << " unrecognized force use " << xsdcCriterionName;
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioHalCapCriterionV2> convertCapCriterionV2ToAidl(
+        const eng_xsd::CriterionType& xsdcCriterion,
+        const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
+    eng_xsd::CriterionTypeType xsdcCriterionType =
+            VALUE_OR_RETURN(getCriterionTypeByName(xsdcCriterion.getType(), xsdcCriterionTypesVec));
+    std::string defaultLiteralValue =
+            xsdcCriterion.has_default() ? xsdcCriterion.get_default() : "";
+    using Tag = AudioHalCapCriterionV2::Tag;
+    if (iequals(xsdcCriterion.getName(), toString(Tag::availableInputDevices))) {
+        return AudioHalCapCriterionV2::make<Tag::availableInputDevices>(
+                VALUE_OR_RETURN(convertDevicesToAidl(xsdcCriterionType)));
+    }
+    if (iequals(xsdcCriterion.getName(), toString(Tag::availableOutputDevices))) {
+        return AudioHalCapCriterionV2::make<Tag::availableOutputDevices>(
+                VALUE_OR_RETURN(convertDevicesToAidl(xsdcCriterionType)));
+    }
+    if (iequals(xsdcCriterion.getName(), toString(Tag::availableInputDevicesAddresses))) {
+        return AudioHalCapCriterionV2::make<Tag::availableInputDevicesAddresses>(
+                VALUE_OR_RETURN(convertDeviceAddressesToAidl(xsdcCriterionType)));
+    }
+    if (iequals(xsdcCriterion.getName(), toString(Tag::availableOutputDevicesAddresses))) {
+        return AudioHalCapCriterionV2::make<Tag::availableOutputDevicesAddresses>(
+                VALUE_OR_RETURN(convertDeviceAddressesToAidl(xsdcCriterionType)));
+    }
+    if (iequals(xsdcCriterion.getName(), toString(Tag::telephonyMode))) {
+        return AudioHalCapCriterionV2::make<Tag::telephonyMode>(
+                VALUE_OR_RETURN(convertTelephonyModesToAidl(xsdcCriterionType)));
+    }
+    if (!fastcmp<strncmp>(xsdcCriterion.getName().c_str(), kXsdcForceConfigForUse,
+            strlen(kXsdcForceConfigForUse))) {
+        return AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(VALUE_OR_RETURN(
+                convertForceUseConfigsToAidl(xsdcCriterion.getName(), xsdcCriterionType)));
+    }
+    LOG(ERROR) << __func__ << " unrecognized criterion " << xsdcCriterion.getName();
+    return unexpected(BAD_VALUE);
+}
+
 ConversionResult<AudioHalCapCriterion> convertCapCriterionToAidl(
         const eng_xsd::CriterionType& xsdcCriterion) {
     AudioHalCapCriterion aidlCapCriterion;
     aidlCapCriterion.name = xsdcCriterion.getName();
     aidlCapCriterion.criterionTypeName = xsdcCriterion.getType();
-    aidlCapCriterion.defaultLiteralValue = xsdcCriterion.get_default();
+    aidlCapCriterion.defaultLiteralValue =
+            xsdcCriterion.has_default() ? 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{};
diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp
index f548903..c77bfca 100644
--- a/audio/aidl/default/alsa/StreamAlsa.cpp
+++ b/audio/aidl/default/alsa/StreamAlsa.cpp
@@ -75,6 +75,10 @@
     }
     decltype(mAlsaDeviceProxies) alsaDeviceProxies;
     for (const auto& device : getDeviceProfiles()) {
+        if ((device.direction == PCM_OUT && mIsInput) ||
+            (device.direction == PCM_IN && !mIsInput)) {
+            continue;
+        }
         alsa::DeviceProxy proxy;
         if (device.isExternal) {
             // Always ask alsa configure as required since the configuration should be supported
@@ -92,6 +96,9 @@
         }
         alsaDeviceProxies.push_back(std::move(proxy));
     }
+    if (alsaDeviceProxies.empty()) {
+        return ::android::NO_INIT;
+    }
     mAlsaDeviceProxies = std::move(alsaDeviceProxies);
     return ::android::OK;
 }
@@ -110,6 +117,7 @@
                                 mReadWriteRetries);
         maxLatency = proxy_get_latency(mAlsaDeviceProxies[0].get());
     } else {
+        alsa::applyGain(buffer, mGain, bytesToTransfer, mConfig.value().format, mConfig->channels);
         for (auto& proxy : mAlsaDeviceProxies) {
             proxy_write_with_retries(proxy.get(), buffer, bytesToTransfer, mReadWriteRetries);
             maxLatency = std::max(maxLatency, proxy_get_latency(proxy.get()));
@@ -159,4 +167,9 @@
     mAlsaDeviceProxies.clear();
 }
 
+ndk::ScopedAStatus StreamAlsa::setGain(float gain) {
+    mGain = gain;
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/alsa/Utils.cpp b/audio/aidl/default/alsa/Utils.cpp
index c08836c..10374f2 100644
--- a/audio/aidl/default/alsa/Utils.cpp
+++ b/audio/aidl/default/alsa/Utils.cpp
@@ -22,6 +22,8 @@
 #include <aidl/android/media/audio/common/AudioFormatType.h>
 #include <aidl/android/media/audio/common/PcmType.h>
 #include <android-base/logging.h>
+#include <audio_utils/primitives.h>
+#include <cutils/compiler.h>
 
 #include "Utils.h"
 #include "core-impl/utils.h"
@@ -80,11 +82,8 @@
 
 const AudioChannelCountToMaskMap& getSupportedChannelOutLayoutMap() {
     static const std::set<AudioChannelLayout> supportedOutChannelLayouts = {
-            DEFINE_CHANNEL_LAYOUT_MASK(MONO),          DEFINE_CHANNEL_LAYOUT_MASK(STEREO),
-            DEFINE_CHANNEL_LAYOUT_MASK(2POINT1),       DEFINE_CHANNEL_LAYOUT_MASK(QUAD),
-            DEFINE_CHANNEL_LAYOUT_MASK(PENTA),         DEFINE_CHANNEL_LAYOUT_MASK(5POINT1),
-            DEFINE_CHANNEL_LAYOUT_MASK(6POINT1),       DEFINE_CHANNEL_LAYOUT_MASK(7POINT1),
-            DEFINE_CHANNEL_LAYOUT_MASK(7POINT1POINT4), DEFINE_CHANNEL_LAYOUT_MASK(22POINT2),
+            DEFINE_CHANNEL_LAYOUT_MASK(MONO),
+            DEFINE_CHANNEL_LAYOUT_MASK(STEREO),
     };
     static const AudioChannelCountToMaskMap outLayouts =
             make_ChannelCountToMaskMap(supportedOutChannelLayouts);
@@ -346,4 +345,68 @@
     return findValueOrDefault(getAudioFormatDescriptorToPcmFormatMap(), aidl, PCM_FORMAT_INVALID);
 }
 
+void applyGain(void* buffer, float gain, size_t bytesToTransfer, enum pcm_format pcmFormat,
+               int channelCount) {
+    if (channelCount != 1 && channelCount != 2) {
+        LOG(WARNING) << __func__ << ": unsupported channel count " << channelCount;
+        return;
+    }
+    if (!getPcmFormatToAudioFormatDescMap().contains(pcmFormat)) {
+        LOG(WARNING) << __func__ << ": unsupported pcm format " << pcmFormat;
+        return;
+    }
+    const float unityGainFloat = 1.0f;
+    if (std::abs(gain - unityGainFloat) < 1e-6) {
+        return;
+    }
+    int numFrames;
+    switch (pcmFormat) {
+        case PCM_FORMAT_S16_LE: {
+            const uint16_t unityGainQ4_12 = u4_12_from_float(unityGainFloat);
+            const uint16_t vl = u4_12_from_float(gain);
+            const uint32_t vrl = (vl << 16) | vl;
+            if (channelCount == 2) {
+                numFrames = bytesToTransfer / sizeof(uint32_t);
+                uint32_t* intBuffer = (uint32_t*)buffer;
+                if (CC_UNLIKELY(vl > unityGainQ4_12)) {
+                    // volume is boosted, so we might need to clamp even though
+                    // we process only one track.
+                    do {
+                        int32_t l = mulRL(1, *intBuffer, vrl) >> 12;
+                        int32_t r = mulRL(0, *intBuffer, vrl) >> 12;
+                        l = clamp16(l);
+                        r = clamp16(r);
+                        *intBuffer++ = (r << 16) | (l & 0xFFFF);
+                    } while (--numFrames);
+                } else {
+                    do {
+                        int32_t l = mulRL(1, *intBuffer, vrl) >> 12;
+                        int32_t r = mulRL(0, *intBuffer, vrl) >> 12;
+                        *intBuffer++ = (r << 16) | (l & 0xFFFF);
+                    } while (--numFrames);
+                }
+            } else {
+                numFrames = bytesToTransfer / sizeof(uint16_t);
+                int16_t* intBuffer = (int16_t*)buffer;
+                if (CC_UNLIKELY(vl > unityGainQ4_12)) {
+                    // volume is boosted, so we might need to clamp even though
+                    // we process only one track.
+                    do {
+                        int32_t mono = mulRL(1, *intBuffer, vrl) >> 12;
+                        *intBuffer++ = clamp16(mono);
+                    } while (--numFrames);
+                } else {
+                    do {
+                        int32_t mono = mulRL(1, *intBuffer, vrl) >> 12;
+                        *intBuffer++ = static_cast<int16_t>(mono & 0xFFFF);
+                    } while (--numFrames);
+                }
+            }
+        } break;
+        default:
+            // TODO(336370745): Implement gain for other supported formats
+            break;
+    }
+}
+
 }  // namespace aidl::android::hardware::audio::core::alsa
diff --git a/audio/aidl/default/alsa/Utils.h b/audio/aidl/default/alsa/Utils.h
index 980f685..a97ea10 100644
--- a/audio/aidl/default/alsa/Utils.h
+++ b/audio/aidl/default/alsa/Utils.h
@@ -59,6 +59,8 @@
     AlsaProxy mProxy;
 };
 
+void applyGain(void* buffer, float gain, size_t bytesToTransfer, enum pcm_format pcmFormat,
+               int channelCount);
 ::aidl::android::media::audio::common::AudioChannelLayout getChannelLayoutMaskFromChannelCount(
         unsigned int channelCount, int isInput);
 ::aidl::android::media::audio::common::AudioChannelLayout getChannelIndexMaskFromChannelCount(
diff --git a/audio/aidl/default/apex/com.android.hardware.audio/Android.bp b/audio/aidl/default/apex/com.android.hardware.audio/Android.bp
index ee92512..8fa429a 100644
--- a/audio/aidl/default/apex/com.android.hardware.audio/Android.bp
+++ b/audio/aidl/default/apex/com.android.hardware.audio/Android.bp
@@ -48,4 +48,11 @@
         "android.hardware.audio.service-aidl.xml",
         "android.hardware.bluetooth.audio.xml",
     ],
+    required: [
+        "aidl_audio_set_configurations_bfbs",
+        "aidl_default_audio_set_configurations_json",
+        "aidl_audio_set_scenarios_bfbs",
+        "aidl_default_audio_set_scenarios_json",
+        "hfp_codec_capabilities_xml",
+    ],
 }
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index 11683d2..2e860d8 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -36,6 +36,7 @@
         <library name="downmix" path="libdownmixaidl.so"/>
         <library name="dynamics_processing" path="libdynamicsprocessingaidl.so"/>
         <library name="equalizersw" path="libequalizersw.so"/>
+        <library name="erasersw" path="liberasersw.so"/>
         <library name="haptic_generator" path="libhapticgeneratoraidl.so"/>
         <library name="loudness_enhancer" path="libloudnessenhanceraidl.so"/>
         <library name="nssw" path="libnssw.so"/>
@@ -75,6 +76,7 @@
         <effect name="bassboost" library="bundle" uuid="8631f300-72e2-11df-b57e-0002a5d5c51b"/>
         <effect name="downmix" library="downmix" uuid="93f04452-e4fe-41cc-91f9-e475b6d1d69f"/>
         <effect name="dynamics_processing" library="dynamics_processing" uuid="e0e6539b-1781-7261-676f-6d7573696340"/>
+        <effect name="eraser" library="erasersw" uuid="fa81ab46-588b-11ed-9b6a-0242ac120002"/>
         <effect name="haptic_generator" library="haptic_generator" uuid="97c4acd1-8b82-4f2f-832e-c2fe5d7a9931"/>
         <effect name="loudness_enhancer" library="loudness_enhancer" uuid="fa415329-2034-4bea-b5dc-5b381c8d1e2c"/>
         <effect name="reverb_env_aux" library="reverb" uuid="4a387fc0-8ab3-11df-8bad-0002a5d5c51b"/>
@@ -140,4 +142,37 @@
         </postprocess>
     -->
 
+    <!-- Device pre/post processor configurations.
+         The device pre/post processor configuration is described in a deviceEffects element and
+         consists in a list of elements each describing pre/post processor settings for a given
+         device.
+         Each device element has a "type" attribute corresponding to the device type (e.g.
+         speaker, bus), an "address" attribute corresponding to the device address and contains a
+         list of "apply" elements indicating one effect to apply.
+         If the device is a source, only pre processing effects are expected, if the
+         device is a sink, only post processing effects are expected.
+         The effect to apply is designated by its name in the "effects" elements.
+         The effect will be enabled by default and the audio framework will automatically add
+         and activate the effect if the given port is involved in an audio patch.
+         If the patch is "HW", the effect must be HW accelerated.
+         Note:
+         -Device are not expected to be always attached. It may be loaded dynamically. As the device
+         effect manager is getting called on any audio patch operation, it will ensure if the given
+         device is involved in an audio patch and attach the requested effect.
+         -Address is optional. If not set, the match to instantiate the device effect will be done
+         using the given type and device (of this type) with empty address only.
+
+       <deviceEffects>
+           <device type="AUDIO_DEVICE_OUT_BUS" address="BUS00_USAGE_MAIN">
+               <apply effect="equalizer"/>
+           </device>
+           <device type="AUDIO_DEVICE_OUT_BUS" address="BUS04_USAGE_VOICE">
+               <apply effect="volume"/>
+           </device>
+           <device type="AUDIO_DEVICE_IN_BUILTIN_MIC" address="bottom">
+               <apply effect="agc"/>
+           </device>
+       </deviceEffects>
+   -->
+
 </audio_effects_conf>
diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt
index 3547f54..3814fe6 100644
--- a/audio/aidl/default/config/audioPolicy/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/api/current.txt
@@ -50,7 +50,7 @@
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_NONE;
-    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_13POINT_360RA;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_13POINT0;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_22POINT2;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT0POINT2;
     enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT1;
@@ -191,6 +191,7 @@
     enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_XHE;
     enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AC3;
     enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AC4;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AC4_L4;
     enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_ALAC;
     enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AMR_NB;
     enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AMR_WB;
diff --git a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
index d93f697..cfe0a6e 100644
--- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
@@ -389,6 +389,7 @@
             <xs:enumeration value="AUDIO_FORMAT_APTX"/>
             <xs:enumeration value="AUDIO_FORMAT_APTX_HD"/>
             <xs:enumeration value="AUDIO_FORMAT_AC4"/>
+            <xs:enumeration value="AUDIO_FORMAT_AC4_L4"/>
             <xs:enumeration value="AUDIO_FORMAT_LDAC"/>
             <xs:enumeration value="AUDIO_FORMAT_MAT"/>
             <xs:enumeration value="AUDIO_FORMAT_MAT_1_0"/>
@@ -462,7 +463,7 @@
             <xs:enumeration value="AUDIO_CHANNEL_OUT_7POINT1POINT4"/>
             <xs:enumeration value="AUDIO_CHANNEL_OUT_9POINT1POINT4"/>
             <xs:enumeration value="AUDIO_CHANNEL_OUT_9POINT1POINT6"/>
-            <xs:enumeration value="AUDIO_CHANNEL_OUT_13POINT_360RA"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_13POINT0"/>
             <xs:enumeration value="AUDIO_CHANNEL_OUT_22POINT2"/>
             <xs:enumeration value="AUDIO_CHANNEL_OUT_MONO_HAPTIC_A"/>
             <xs:enumeration value="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A"/>
diff --git a/audio/aidl/default/config/audioPolicy/capengine/Android.bp b/audio/aidl/default/config/audioPolicy/capengine/Android.bp
new file mode 100644
index 0000000..cb99923
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/capengine/Android.bp
@@ -0,0 +1,17 @@
+package {
+    default_team: "trendy_team_android_media_audio_framework",
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+xsd_config {
+    name: "audio_policy_capengine_configuration_aidl_default",
+    srcs: ["PolicyConfigurableDomains.xsd"],
+    package_name: "android.audio.policy.capengine.configuration",
+    nullability: true,
+    root_elements: ["ConfigurableDomains"],
+}
diff --git a/audio/aidl/default/config/audioPolicy/capengine/PolicyConfigurableDomains.xsd b/audio/aidl/default/config/audioPolicy/capengine/PolicyConfigurableDomains.xsd
new file mode 100644
index 0000000..4e7c0bb
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/capengine/PolicyConfigurableDomains.xsd
@@ -0,0 +1,467 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <!-- BEGIN W3cXmlAttributes.xsd -->
+    <xs:annotation>
+        <xs:documentation>
+            See http://www.w3.org/XML/1998/namespace.html and
+            http://www.w3.org/TR/REC-xml for information about this namespace.
+
+            This schema document describes the XML namespace, in a form
+            suitable for import by other schema documents.
+
+            Note that local names in this namespace are intended to be defined
+            only by the World Wide Web Consortium or its subgroups.  The
+            following names are currently defined in this namespace and should
+            not be used with conflicting semantics by any Working Group,
+            specification, or document instance:
+
+            base (as an attribute name): denotes an attribute whose value
+            provides a URI to be used as the base for interpreting any
+            relative URIs in the scope of the element on which it
+            appears; its value is inherited.  This name is reserved
+            by virtue of its definition in the XML Base specification.
+
+            id   (as an attribute name): denotes an attribute whose value
+            should be interpreted as if declared to be of type ID.
+            The xml:id specification is not yet a W3C Recommendation,
+            but this attribute is included here to facilitate experimentation
+            with the mechanisms it proposes.  Note that it is _not_ included
+            in the specialAttrs attribute group.
+
+            lang (as an attribute name): denotes an attribute whose value
+            is a language code for the natural language of the content of
+            any element; its value is inherited.  This name is reserved
+            by virtue of its definition in the XML specification.
+
+            space (as an attribute name): denotes an attribute whose
+            value is a keyword indicating what whitespace processing
+            discipline is intended for the content of the element; its
+            value is inherited.  This name is reserved by virtue of its
+            definition in the XML specification.
+
+            Father (in any context at all): denotes Jon Bosak, the chair of
+            the original XML Working Group.  This name is reserved by
+            the following decision of the W3C XML Plenary and
+            XML Coordination groups:
+
+            In appreciation for his vision, leadership and dedication
+            the W3C XML Plenary on this 10th day of February, 2000
+            reserves for Jon Bosak in perpetuity the XML name
+            xml:Father
+        </xs:documentation>
+    </xs:annotation>
+
+    <xs:annotation>
+        <xs:documentation>This schema defines attributes and an attribute group
+            suitable for use by
+            schemas wishing to allow xml:base, xml:lang, xml:space or xml:id
+            attributes on elements they define.
+
+            To enable this, such a schema must import this schema
+            for the XML namespace, e.g. as follows:
+            &lt;schema . . .>
+            . . .
+            &lt;import namespace="http://www.w3.org/XML/1998/namespace"
+            schemaLocation="http://www.w3.org/2005/08/xml.xsd"/>
+
+            Subsequently, qualified reference to any of the attributes
+            or the group defined below will have the desired effect, e.g.
+
+            &lt;type . . .>
+            . . .
+            &lt;attributeGroup ref="xml:specialAttrs"/>
+
+            will define a type which will schema-validate an instance
+            element with any of those attributes</xs:documentation>
+    </xs:annotation>
+
+    <xs:annotation>
+        <xs:documentation>In keeping with the XML Schema WG's standard versioning
+            policy, this schema document will persist at
+            http://www.w3.org/2005/08/xml.xsd.
+            At the date of issue it can also be found at
+            http://www.w3.org/2001/xml.xsd.
+            The schema document at that URI may however change in the future,
+            in order to remain compatible with the latest version of XML Schema
+            itself, or with the XML namespace itself.  In other words, if the XML
+            Schema or XML namespaces change, the version of this document at
+            http://www.w3.org/2001/xml.xsd will change
+            accordingly; the version at
+            http://www.w3.org/2005/08/xml.xsd will not change.
+        </xs:documentation>
+    </xs:annotation>
+
+    <xs:attribute name="lang">
+        <xs:annotation>
+            <xs:documentation>Attempting to install the relevant ISO 2- and 3-letter
+                codes as the enumerated possible values is probably never
+                going to be a realistic possibility.  See
+                RFC 3066 at http://www.ietf.org/rfc/rfc3066.txt and the IANA registry
+                at http://www.iana.org/assignments/lang-tag-apps.htm for
+                further information.
+
+                The union allows for the 'un-declaration' of xml:lang with
+                the empty string.</xs:documentation>
+        </xs:annotation>
+        <xs:simpleType>
+            <xs:union memberTypes="xs:language">
+                <xs:simpleType name="langEnum">
+                    <xs:restriction base="xs:string">
+                        <xs:enumeration value=""/>
+                    </xs:restriction>
+                </xs:simpleType>
+            </xs:union>
+        </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="space">
+        <xs:simpleType name="spaceEnum">
+            <xs:restriction base="xs:NCName">
+                <xs:enumeration value="default"/>
+                <xs:enumeration value="preserve"/>
+            </xs:restriction>
+        </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="base" type="xs:anyURI">
+        <xs:annotation>
+            <xs:documentation>See http://www.w3.org/TR/xmlbase/ for
+                information about this attribute.</xs:documentation>
+        </xs:annotation>
+    </xs:attribute>
+
+    <xs:attribute name="id" type="xs:ID">
+        <xs:annotation>
+            <xs:documentation>See http://www.w3.org/TR/xml-id/ for
+                information about this attribute.</xs:documentation>
+        </xs:annotation>
+    </xs:attribute>
+
+    <xs:attributeGroup name="specialAttrs">
+        <xs:attribute ref="xml:base"/>
+        <xs:attribute ref="xml:lang"/>
+        <xs:attribute ref="xml:space"/>
+    </xs:attributeGroup>
+    <!-- END W3cXmlAttributes.xsd -->
+
+    <!-- BEGIN ParameterSettings.xsd -->
+    <!-- BUG b/147297854 - removed "abstract" from type definition -->
+    <xs:complexType name="BooleanParameterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
+            </xs:extension>
+            <!--xs:restriction base="xs:string">
+                <xs:pattern value="([01][\s]*)+"/>
+                <xs:pattern value="((0x0|0x1)[\s]*)+"/>
+                <xs:attribute name="Name" type="xs:string" use="required"/>
+            </xs:restriction-->
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:complexType name="IntegerParameterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
+            </xs:extension>
+            <!--xs:restriction base="xs:string">
+                <xs:pattern value="(0|([+-]?[1-9][0-9]*))(\s+(0|([+-]?[1-9][0-9]*)))*"/>
+                <xs:pattern value="(0x[0-9a-fA-F]+)(\s+(0x[0-9a-fA-F]+))*"/>
+                <xs:attribute name="Name" type="xs:string" use="required"/>
+            </xs:restriction-->
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:complexType name="EnumParameterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
+            </xs:extension>
+            <!--xs:extension base="xs:string">
+                <xs:attribute name="Name" type="xs:string" use="required"/>
+            </xs:extension-->
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:complexType name="PointParameterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
+            </xs:extension>
+            <!--xs:restriction base="xs:string">
+                <xs:pattern value="((0|[+-]?0\.[0-9]+|(([+-]?[1-9][0-9]*)(\.[0-9]+)?))([Ee][+-]?[0-9]+)?)(\s+(0|[+-]?0\.[0-9]+|(([+-]?[1-9][0-9]*)(\.[0-9]+)?))([Ee][+-]?[0-9]+)?)*"/>
+                <xs:pattern value="(0x[0-9a-fA-F]+)(\s+(0x[0-9a-fA-F]+))*"/>
+                <xs:attribute name="Name" type="xs:NMTOKEN" use="required"/>
+            </xs:restriction-->
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:complexType name="BitParameterBlockType">
+        <xs:sequence>
+            <xs:element name="BitParameter" maxOccurs="unbounded" type="IntegerParameterType"/>
+        </xs:sequence>
+        <xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="StringParameterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:group name="ParameterBlockGroup">
+        <xs:choice>
+            <xs:element name="BooleanParameter" type="BooleanParameterType"/>
+            <xs:element name="IntegerParameter" type="IntegerParameterType"/>
+            <xs:element name="EnumParameter" type="EnumParameterType"/>
+            <xs:element name="FixedPointParameter" type="PointParameterType"/>
+            <xs:element name="FloatingPointParameter" type="PointParameterType"/>
+            <xs:element name="BitParameterBlock" type="BitParameterBlockType">
+                <xs:unique name="BitParameterBlockSubElementsUniqueness">
+                    <xs:selector xpath="*"/>
+                    <xs:field xpath="@Name"/>
+                </xs:unique>
+            </xs:element>
+            <xs:element name="StringParameter" type="StringParameterType"/>
+            <!--xs:element name="Component" type="ParameterBlockType"/-->
+            <xs:element name="ParameterBlock" type="ParameterBlockType">
+                <xs:unique name="ParameterBlockSubElementsUniqueness">
+                    <xs:selector xpath="*"/>
+                    <xs:field xpath="@Name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:choice>
+    </xs:group>
+    <xs:complexType name="ParameterBlockType">
+        <xs:sequence>
+            <xs:group ref="ParameterBlockGroup" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="Name" type="xs:NMTOKEN" use="required"/>
+    </xs:complexType>
+    <!-- END ParameterSettings.xsd -->
+
+    <!-- BEGIN ConfigurableDomain.xsd -->
+    <xs:complexType name="SelectionCriterionRuleType">
+        <xs:attribute name="SelectionCriterion" type="xs:NMTOKEN" use="required"/>
+        <xs:attribute name="MatchesWhen" use="required">
+            <xs:simpleType name="MatchesWhenEnum">
+                <xs:restriction base="xs:NMTOKEN">
+                    <xs:enumeration value="Is"/>
+                    <xs:enumeration value="IsNot"/>
+                    <xs:enumeration value="Includes"/>
+                    <xs:enumeration value="Excludes"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="Value" use="required" type="xs:NMTOKEN"/>
+    </xs:complexType>
+    <xs:group name="RuleGroup">
+        <xs:choice>
+            <xs:element name="CompoundRule" type="CompoundRuleType"/>
+            <xs:element name="SelectionCriterionRule" type="SelectionCriterionRuleType"/>
+        </xs:choice>
+    </xs:group>
+    <xs:complexType name="CompoundRuleType">
+        <xs:sequence>
+            <xs:group ref="RuleGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="Type">
+            <xs:simpleType name="TypeEnum">
+                <xs:restriction base="xs:NMTOKEN">
+                    <xs:enumeration value="Any"/>
+                    <xs:enumeration value="All"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="ConfigurationsType">
+        <xs:sequence>
+            <xs:element maxOccurs="unbounded" name="Configuration">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="CompoundRule" type="CompoundRuleType" minOccurs="0" maxOccurs="1"/>
+                    </xs:sequence>
+                    <xs:attribute name="Name" use="required" type="xs:NCName"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:group name="ComponentGroup">
+        <xs:sequence>
+            <xs:group ref="ParameterBlockGroup"/>
+        </xs:sequence>
+    </xs:group>
+    <xs:complexType name="ComponentType">
+        <xs:sequence>
+            <xs:choice>
+                <xs:group ref="ComponentGroup" maxOccurs="unbounded"/>
+                <xs:element name="Subsystem" type="ComponentType" maxOccurs="unbounded"/>
+            </xs:choice>
+        </xs:sequence>
+        <xs:attribute name="Name" use="required" type="xs:NCName"/>
+    </xs:complexType>
+    <xs:complexType name="ConfigurableElementsType">
+        <xs:sequence>
+            <xs:element maxOccurs="unbounded" minOccurs="0" name="ConfigurableElement">
+                <xs:complexType>
+                    <xs:attribute name="Path" use="required">
+                        <xs:simpleType>
+                            <xs:restriction base="xs:anyURI">
+                                <xs:pattern value="/.*[^/]"/>
+                            </xs:restriction>
+                        </xs:simpleType>
+                    </xs:attribute>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="ConfigurableElementSettingsType">
+        <xs:choice>
+            <xs:element name="BooleanParameter" type="BooleanParameterType"/>
+            <xs:element name="IntegerParameter" type="IntegerParameterType"/>
+            <xs:element name="EnumParameter" type="EnumParameterType"/>
+            <xs:element name="FixedPointParameter" type="PointParameterType"/>
+            <xs:element name="FloatingPointParameter" type="PointParameterType"/>
+            <xs:element name="BitParameter" type="IntegerParameterType"/>
+            <xs:element name="BitParameterBlock" type="BitParameterBlockType">
+                <xs:unique name="BitParameterBlockSubElementsUniqueness">
+                    <xs:selector xpath="*"/>
+                    <xs:field xpath="@Name"/>
+                </xs:unique>
+            </xs:element>
+            <xs:element name="StringParameter" type="StringParameterType"/>
+            <!--xs:element name="Component" type="ParameterBlockType"/-->
+            <xs:element name="ParameterBlock" type="ParameterBlockType">
+                <xs:unique name="ParameterBlockSubElementsUniqueness">
+                    <xs:selector xpath="*"/>
+                    <xs:field xpath="@Name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:choice>
+        <!--xs:choice>
+            <xs:element name="BitParameter" type="IntegerParameterType"/>
+            <xs:group ref="ComponentGroup"/>
+        </xs:choice-->
+        <xs:attribute name="Path" use="required">
+            <xs:simpleType>
+                <xs:restriction base="xs:anyURI">
+                    <xs:pattern value="/.*[^/]"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="SettingsType">
+        <xs:sequence>
+            <xs:element maxOccurs="unbounded" minOccurs="0" name="Configuration">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="ConfigurableElement" minOccurs="0" maxOccurs="unbounded" type="ConfigurableElementSettingsType"/>
+                    </xs:sequence>
+                    <xs:attribute name="Name" use="required" type="xs:NCName"/>
+                </xs:complexType>
+                <xs:unique name="ConfigurableElementUniqueness">
+                    <xs:selector xpath="ConfigurableElement"/>
+                    <xs:field xpath="@Path"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="ConfigurableDomainType">
+        <xs:sequence>
+            <xs:element name="Configurations" type="ConfigurationsType"/>
+            <xs:element name="ConfigurableElements" type="ConfigurableElementsType"/>
+            <xs:element name="Settings" type="SettingsType" minOccurs="0"/>
+        </xs:sequence>
+        <xs:attribute name="Name" use="required" type="xs:NCName"/>
+        <xs:attribute name="SequenceAware" use="optional" type="xs:boolean" default="false"/>
+    </xs:complexType>
+    <xs:element name="ConfigurableDomain" type="ConfigurableDomainType"/>
+    <!-- END ConfigurableDomain.xsd -->
+
+    <!-- BEGIN ConfigurableDomains.xsd -->
+    <xs:element name="ConfigurableDomains">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element maxOccurs="unbounded" name="ConfigurableDomain" type="ConfigurableDomainType">
+                    <xs:key name="ConfigurableElementKey">
+                        <xs:selector xpath="ConfigurableElements/ConfigurableElement"/>
+                        <xs:field xpath="@Path"/>
+                    </xs:key>
+                    <xs:keyref refer="ConfigurableElementKey" name="ConfigurableDomainReference">
+                        <xs:selector xpath="Settings/Configuration/ConfigurableElement"/>
+                        <xs:field xpath="@Path"/>
+                    </xs:keyref>
+                    <xs:key name="ConfigurationKey">
+                        <xs:selector xpath="Configurations/Configuration"/>
+                        <xs:field xpath="@Name"/>
+                    </xs:key>
+                    <xs:keyref refer="ConfigurationKey" name="ConfigurationReference2">
+                        <xs:selector xpath="ConfigurableElements/ConfigurableElement/Configuration"/>
+                        <xs:field xpath="@Name"/>
+                    </xs:keyref>
+                    <xs:keyref refer="ConfigurationKey" name="ConfigurationReference">
+                        <xs:selector xpath="Settings/Configuration"/>
+                        <xs:field xpath="@Name"/>
+                    </xs:keyref>
+                </xs:element>
+            </xs:sequence>
+            <xs:attribute name="SystemClassName" use="required" type="xs:NCName"/>
+        </xs:complexType>
+        <xs:unique name="ConfigurableDomainUniqueness">
+            <xs:selector xpath="ConfigurableDomain"/>
+            <xs:field xpath="@Name"/>
+        </xs:unique>
+    </xs:element>
+    <!-- END ConfigurableDomains.xsd -->
+
+    <xs:simpleType name="ParameterNameEnumType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="volume_profile"/>
+
+            <xs:enumeration value="communication"/>
+            <xs:enumeration value="ambient"/>
+            <xs:enumeration value="builtin_mic"/>
+            <xs:enumeration value="bluetooth_sco_headset"/>
+            <xs:enumeration value="wired_headset"/>
+            <xs:enumeration value="hdmi"/>
+            <xs:enumeration value="telephony_rx"/>
+            <xs:enumeration value="back_mic"/>
+            <xs:enumeration value="remote_submix"/>
+            <xs:enumeration value="anlg_dock_headset"/>
+            <xs:enumeration value="dgtl_dock_headset"/>
+            <xs:enumeration value="usb_accessory"/>
+            <xs:enumeration value="usb_device"/>
+            <xs:enumeration value="fm_tuner"/>
+            <xs:enumeration value="tv_tuner"/>
+            <xs:enumeration value="line"/>
+            <xs:enumeration value="spdif"/>
+            <xs:enumeration value="bluetooth_a2dp" />
+            <xs:enumeration value="loopback" />
+            <xs:enumeration value="ip" />
+            <xs:enumeration value="bus" />
+            <xs:enumeration value="proxy"/>
+            <xs:enumeration value="usb_headset"/>
+            <xs:enumeration value="bluetooth_ble"/>
+            <xs:enumeration value="hdmi_arc"/>
+            <xs:enumeration value="echo_reference"/>
+            <xs:enumeration value="ble_headset"/>
+            <xs:enumeration value="stub"/>
+            <xs:enumeration value="hdmi_earc"/>
+
+            <xs:enumeration value="device_address"/>
+
+            <xs:enumeration value="earpiece" />
+            <xs:enumeration value="speaker" />
+            <xs:enumeration value="wired_headphone" />
+            <xs:enumeration value="bluetooth_sco" />
+            <xs:enumeration value="bluetooth_sco_carkit"/>
+            <xs:enumeration value="bluetooth_a2dp_headphones"/>
+            <xs:enumeration value="bluetooth_a2dp_speaker"/>
+            <xs:enumeration value="telephony_tx"/>
+            <xs:enumeration value="fm"/>
+            <xs:enumeration value="aux_line"/>
+            <xs:enumeration value="speaker_safe"/>
+            <xs:enumeration value="hearing_aid" />
+            <xs:enumeration value="echo_canceller" />
+            <xs:enumeration value="ble_speaker" />
+            <xs:enumeration value="ble_broadcast" />
+        </xs:restriction>
+    </xs:simpleType>
+</xs:schema>
diff --git a/audio/aidl/default/config/audioPolicy/capengine/api/current.txt b/audio/aidl/default/config/audioPolicy/capengine/api/current.txt
new file mode 100644
index 0000000..481abbf
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/capengine/api/current.txt
@@ -0,0 +1,264 @@
+// Signature format: 2.0
+package android.audio.policy.capengine.configuration {
+
+  public class BitParameterBlockType {
+    ctor public BitParameterBlockType();
+    method @Nullable public java.util.List<android.audio.policy.capengine.configuration.IntegerParameterType> getBitParameter();
+    method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName();
+    method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType);
+  }
+
+  public class BooleanParameterType {
+    ctor public BooleanParameterType();
+    method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName();
+    method @Nullable public String getValue();
+    method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType);
+    method public void setValue(@Nullable String);
+  }
+
+  public class ComponentType {
+    ctor public ComponentType();
+    method @Nullable public String getName();
+    method @Nullable public java.util.List<android.audio.policy.capengine.configuration.ComponentType> getSubsystem_optional();
+    method public void setName(@Nullable String);
+  }
+
+  public class CompoundRuleType {
+    ctor public CompoundRuleType();
+    method @Nullable public android.audio.policy.capengine.configuration.CompoundRuleType getCompoundRule_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.SelectionCriterionRuleType getSelectionCriterionRule_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.TypeEnum getType();
+    method public void setCompoundRule_optional(@Nullable android.audio.policy.capengine.configuration.CompoundRuleType);
+    method public void setSelectionCriterionRule_optional(@Nullable android.audio.policy.capengine.configuration.SelectionCriterionRuleType);
+    method public void setType(@Nullable android.audio.policy.capengine.configuration.TypeEnum);
+  }
+
+  public class ConfigurableDomainType {
+    ctor public ConfigurableDomainType();
+    method @Nullable public android.audio.policy.capengine.configuration.ConfigurableElementsType getConfigurableElements();
+    method @Nullable public android.audio.policy.capengine.configuration.ConfigurationsType getConfigurations();
+    method @Nullable public String getName();
+    method @Nullable public boolean getSequenceAware();
+    method @Nullable public android.audio.policy.capengine.configuration.SettingsType getSettings();
+    method public void setConfigurableElements(@Nullable android.audio.policy.capengine.configuration.ConfigurableElementsType);
+    method public void setConfigurations(@Nullable android.audio.policy.capengine.configuration.ConfigurationsType);
+    method public void setName(@Nullable String);
+    method public void setSequenceAware(@Nullable boolean);
+    method public void setSettings(@Nullable android.audio.policy.capengine.configuration.SettingsType);
+  }
+
+  public class ConfigurableDomains {
+    ctor public ConfigurableDomains();
+    method @Nullable public java.util.List<android.audio.policy.capengine.configuration.ConfigurableDomainType> getConfigurableDomain();
+    method @Nullable public String getSystemClassName();
+    method public void setSystemClassName(@Nullable String);
+  }
+
+  public class ConfigurableElementSettingsType {
+    ctor public ConfigurableElementSettingsType();
+    method @Nullable public android.audio.policy.capengine.configuration.BitParameterBlockType getBitParameterBlock_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.IntegerParameterType getBitParameter_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.BooleanParameterType getBooleanParameter_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.EnumParameterType getEnumParameter_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.PointParameterType getFixedPointParameter_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.PointParameterType getFloatingPointParameter_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.IntegerParameterType getIntegerParameter_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.ParameterBlockType getParameterBlock_optional();
+    method @Nullable public String getPath();
+    method @Nullable public android.audio.policy.capengine.configuration.StringParameterType getStringParameter_optional();
+    method public void setBitParameterBlock_optional(@Nullable android.audio.policy.capengine.configuration.BitParameterBlockType);
+    method public void setBitParameter_optional(@Nullable android.audio.policy.capengine.configuration.IntegerParameterType);
+    method public void setBooleanParameter_optional(@Nullable android.audio.policy.capengine.configuration.BooleanParameterType);
+    method public void setEnumParameter_optional(@Nullable android.audio.policy.capengine.configuration.EnumParameterType);
+    method public void setFixedPointParameter_optional(@Nullable android.audio.policy.capengine.configuration.PointParameterType);
+    method public void setFloatingPointParameter_optional(@Nullable android.audio.policy.capengine.configuration.PointParameterType);
+    method public void setIntegerParameter_optional(@Nullable android.audio.policy.capengine.configuration.IntegerParameterType);
+    method public void setParameterBlock_optional(@Nullable android.audio.policy.capengine.configuration.ParameterBlockType);
+    method public void setPath(@Nullable String);
+    method public void setStringParameter_optional(@Nullable android.audio.policy.capengine.configuration.StringParameterType);
+  }
+
+  public class ConfigurableElementsType {
+    ctor public ConfigurableElementsType();
+    method @Nullable public java.util.List<android.audio.policy.capengine.configuration.ConfigurableElementsType.ConfigurableElement> getConfigurableElement();
+  }
+
+  public static class ConfigurableElementsType.ConfigurableElement {
+    ctor public ConfigurableElementsType.ConfigurableElement();
+    method @Nullable public String getPath();
+    method public void setPath(@Nullable String);
+  }
+
+  public class ConfigurationsType {
+    ctor public ConfigurationsType();
+    method @Nullable public java.util.List<android.audio.policy.capengine.configuration.ConfigurationsType.Configuration> getConfiguration();
+  }
+
+  public static class ConfigurationsType.Configuration {
+    ctor public ConfigurationsType.Configuration();
+    method @Nullable public android.audio.policy.capengine.configuration.CompoundRuleType getCompoundRule();
+    method @Nullable public String getName();
+    method public void setCompoundRule(@Nullable android.audio.policy.capengine.configuration.CompoundRuleType);
+    method public void setName(@Nullable String);
+  }
+
+  public class EnumParameterType {
+    ctor public EnumParameterType();
+    method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName();
+    method @Nullable public String getValue();
+    method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType);
+    method public void setValue(@Nullable String);
+  }
+
+  public class IntegerParameterType {
+    ctor public IntegerParameterType();
+    method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName();
+    method @Nullable public String getValue();
+    method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType);
+    method public void setValue(@Nullable String);
+  }
+
+  public enum LangEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.capengine.configuration.LangEnum EMPTY;
+  }
+
+  public enum MatchesWhenEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.capengine.configuration.MatchesWhenEnum Excludes;
+    enum_constant public static final android.audio.policy.capengine.configuration.MatchesWhenEnum Includes;
+    enum_constant public static final android.audio.policy.capengine.configuration.MatchesWhenEnum Is;
+    enum_constant public static final android.audio.policy.capengine.configuration.MatchesWhenEnum IsNot;
+  }
+
+  public class ParameterBlockType {
+    ctor public ParameterBlockType();
+    method @Nullable public android.audio.policy.capengine.configuration.BitParameterBlockType getBitParameterBlock_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.BooleanParameterType getBooleanParameter_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.EnumParameterType getEnumParameter_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.PointParameterType getFixedPointParameter_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.PointParameterType getFloatingPointParameter_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.IntegerParameterType getIntegerParameter_optional();
+    method @Nullable public String getName();
+    method @Nullable public android.audio.policy.capengine.configuration.ParameterBlockType getParameterBlock_optional();
+    method @Nullable public android.audio.policy.capengine.configuration.StringParameterType getStringParameter_optional();
+    method public void setBitParameterBlock_optional(@Nullable android.audio.policy.capengine.configuration.BitParameterBlockType);
+    method public void setBooleanParameter_optional(@Nullable android.audio.policy.capengine.configuration.BooleanParameterType);
+    method public void setEnumParameter_optional(@Nullable android.audio.policy.capengine.configuration.EnumParameterType);
+    method public void setFixedPointParameter_optional(@Nullable android.audio.policy.capengine.configuration.PointParameterType);
+    method public void setFloatingPointParameter_optional(@Nullable android.audio.policy.capengine.configuration.PointParameterType);
+    method public void setIntegerParameter_optional(@Nullable android.audio.policy.capengine.configuration.IntegerParameterType);
+    method public void setName(@Nullable String);
+    method public void setParameterBlock_optional(@Nullable android.audio.policy.capengine.configuration.ParameterBlockType);
+    method public void setStringParameter_optional(@Nullable android.audio.policy.capengine.configuration.StringParameterType);
+  }
+
+  public enum ParameterNameEnumType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ambient;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType anlg_dock_headset;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType aux_line;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType back_mic;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ble_broadcast;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ble_headset;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ble_speaker;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_a2dp;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_a2dp_headphones;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_a2dp_speaker;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_ble;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_sco;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_sco_carkit;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_sco_headset;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType builtin_mic;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bus;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType communication;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType device_address;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType dgtl_dock_headset;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType earpiece;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType echo_canceller;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType echo_reference;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType fm;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType fm_tuner;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType hdmi;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType hdmi_arc;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType hdmi_earc;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType hearing_aid;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ip;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType line;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType loopback;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType proxy;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType remote_submix;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType spdif;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType speaker;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType speaker_safe;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType stub;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType telephony_rx;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType telephony_tx;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType tv_tuner;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType usb_accessory;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType usb_device;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType usb_headset;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType volume_profile;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType wired_headphone;
+    enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType wired_headset;
+  }
+
+  public class PointParameterType {
+    ctor public PointParameterType();
+    method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName();
+    method @Nullable public String getValue();
+    method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType);
+    method public void setValue(@Nullable String);
+  }
+
+  public class SelectionCriterionRuleType {
+    ctor public SelectionCriterionRuleType();
+    method @Nullable public android.audio.policy.capengine.configuration.MatchesWhenEnum getMatchesWhen();
+    method @Nullable public String getSelectionCriterion();
+    method @Nullable public String getValue();
+    method public void setMatchesWhen(@Nullable android.audio.policy.capengine.configuration.MatchesWhenEnum);
+    method public void setSelectionCriterion(@Nullable String);
+    method public void setValue(@Nullable String);
+  }
+
+  public class SettingsType {
+    ctor public SettingsType();
+    method @Nullable public java.util.List<android.audio.policy.capengine.configuration.SettingsType.Configuration> getConfiguration();
+  }
+
+  public static class SettingsType.Configuration {
+    ctor public SettingsType.Configuration();
+    method @Nullable public java.util.List<android.audio.policy.capengine.configuration.ConfigurableElementSettingsType> getConfigurableElement();
+    method @Nullable public String getName();
+    method public void setName(@Nullable String);
+  }
+
+  public enum SpaceEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.capengine.configuration.SpaceEnum _default;
+    enum_constant public static final android.audio.policy.capengine.configuration.SpaceEnum preserve;
+  }
+
+  public class StringParameterType {
+    ctor public StringParameterType();
+    method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName();
+    method @Nullable public String getValue();
+    method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType);
+    method public void setValue(@Nullable String);
+  }
+
+  public enum TypeEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.capengine.configuration.TypeEnum All;
+    enum_constant public static final android.audio.policy.capengine.configuration.TypeEnum Any;
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method @Nullable public static android.audio.policy.capengine.configuration.ConfigurableDomains readConfigurableDomains(@NonNull java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method @Nullable public static String readText(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static void skip(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+  }
+
+}
+
diff --git a/audio/aidl/default/config/audioPolicy/capengine/api/last_current.txt b/audio/aidl/default/config/audioPolicy/capengine/api/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/capengine/api/last_current.txt
diff --git a/audio/aidl/default/config/audioPolicy/capengine/api/last_removed.txt b/audio/aidl/default/config/audioPolicy/capengine/api/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/capengine/api/last_removed.txt
diff --git a/audio/aidl/default/config/audioPolicy/capengine/api/removed.txt b/audio/aidl/default/config/audioPolicy/capengine/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/capengine/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/audio/aidl/default/config/audioPolicy/engine/api/current.txt b/audio/aidl/default/config/audioPolicy/engine/api/current.txt
index 063b05d..017362f 100644
--- a/audio/aidl/default/config/audioPolicy/engine/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/engine/api/current.txt
@@ -148,6 +148,45 @@
     method public void setValue(@Nullable java.util.List<android.audio.policy.engine.configuration.FlagType>);
   }
 
+  public enum ForcedConfigCommunicationDeviceType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigCommunicationDeviceType BT_BLE;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigCommunicationDeviceType BT_SCO;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigCommunicationDeviceType NONE;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigCommunicationDeviceType SPEAKER;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigCommunicationDeviceType WIRED_ACCESSORY;
+  }
+
+  public enum ForcedConfigDockType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigDockType ANALOG_DOCK;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigDockType BT_CAR_DOCK;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigDockType BT_DESK_DOCK;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigDockType DIGITAL_DOCK;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigDockType NONE;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigDockType WIRED_ACCESSORY;
+  }
+
+  public enum ForcedConfigMediaDeviceType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType ANALOG_DOCK;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType BT_A2DP;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType DIGITAL_DOCK;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType HEADPHONES;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType NONE;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType NO_BT_A2DP;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType SPEAKER;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType WIRED_ACCESSORY;
+  }
+
+  public enum ForcedEncodingSourroundConfigType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedEncodingSourroundConfigType ALWAYS;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedEncodingSourroundConfigType MANUAL;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedEncodingSourroundConfigType NEVER;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedEncodingSourroundConfigType UNSPECIFIED;
+  }
+
   public enum PfwCriterionTypeEnum {
     method @NonNull public String getRawName();
     enum_constant public static final android.audio.policy.engine.configuration.PfwCriterionTypeEnum exclusive;
@@ -162,7 +201,9 @@
   public static class ProductStrategies.ProductStrategy {
     ctor public ProductStrategies.ProductStrategy();
     method @Nullable public java.util.List<android.audio.policy.engine.configuration.AttributesGroup> getAttributesGroup();
+    method @Nullable public int getId();
     method @Nullable public String getName();
+    method public void setId(@Nullable int);
     method public void setName(@Nullable String);
   }
 
@@ -242,10 +283,8 @@
     ctor public ValueType();
     method @Nullable public String getAndroid_type();
     method @Nullable public String getLiteral();
-    method @Nullable public long getNumerical();
     method public void setAndroid_type(@Nullable String);
     method public void setLiteral(@Nullable String);
-    method public void setNumerical(@Nullable long);
   }
 
   public class ValuesType {
diff --git a/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
index 40396bb..cfd99eb 100644
--- a/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
@@ -105,6 +105,8 @@
                         <xs:element name="AttributesGroup" type="AttributesGroup" minOccurs="1" maxOccurs="unbounded"/>
                     </xs:sequence>
                     <xs:attribute name="name" type="xs:string" use="required"/>
+                    <!-- Only needs to be specified for vendor strategies. -->
+                    <xs:attribute name="id" type="xs:int" use="optional"/>
                 </xs:complexType>
             </xs:element>
         </xs:sequence>
@@ -188,8 +190,19 @@
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="valueType">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Criterion type is provided as a pair of 'human readable' string (referred as the
+                literal part, that will allow to express 'human readable' rules and an optional
+                android type.
+                This android type is reserved for device type mapping with parameter framework
+                representation on a bitfield (Only one bit is expected to represent a device) and
+                android representation of a type that may use several bits.
+                The lookup table will allow wrap android device type to parameter framework device
+                types data model.
+            </xs:documentation>
+        </xs:annotation>
         <xs:attribute name="literal" type="xs:string" use="required"/>
-        <xs:attribute name="numerical" type="xs:long" use="required"/>
         <xs:attribute name="android_type" type="longDecimalOrHexType" use="optional"/>
     </xs:complexType>
 
@@ -395,6 +408,49 @@
         </xs:restriction>
     </xs:simpleType>
 
+    <xs:simpleType name="forcedConfigCommunicationDeviceType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="NONE"/>
+            <xs:enumeration value="SPEAKER"/>
+            <xs:enumeration value="BT_SCO"/>
+            <xs:enumeration value="BT_BLE"/>
+            <xs:enumeration value="WIRED_ACCESSORY"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="forcedConfigMediaDeviceType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="NONE"/>
+            <xs:enumeration value="SPEAKER"/>
+            <xs:enumeration value="HEADPHONES"/>
+            <xs:enumeration value="BT_A2DP"/>
+            <xs:enumeration value="ANALOG_DOCK"/>
+            <xs:enumeration value="DIGITAL_DOCK"/>
+            <xs:enumeration value="WIRED_ACCESSORY"/>
+            <xs:enumeration value="NO_BT_A2DP"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="forcedConfigDockType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="NONE"/>
+            <xs:enumeration value="BT_CAR_DOCK"/>
+            <xs:enumeration value="BT_DESK_DOCK"/>
+            <xs:enumeration value="ANALOG_DOCK"/>
+            <xs:enumeration value="DIGITAL_DOCK"/>
+            <xs:enumeration value="WIRED_ACCESSORY"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="forcedEncodingSourroundConfigType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="UNSPECIFIED"/>
+            <xs:enumeration value="NEVER"/>
+            <xs:enumeration value="ALWAYS"/>
+            <xs:enumeration value="MANUAL"/>
+        </xs:restriction>
+    </xs:simpleType>
+
     <xs:simpleType name="sourceEnumType">
         <xs:restriction base="xs:string">
             <xs:enumeration value="AUDIO_SOURCE_DEFAULT"/>
diff --git a/audio/aidl/default/StreamSwitcher.cpp b/audio/aidl/default/deprecated/StreamSwitcher.cpp
similarity index 95%
rename from audio/aidl/default/StreamSwitcher.cpp
rename to audio/aidl/default/deprecated/StreamSwitcher.cpp
index 8ba15a8..f1e0f52 100644
--- a/audio/aidl/default/StreamSwitcher.cpp
+++ b/audio/aidl/default/deprecated/StreamSwitcher.cpp
@@ -23,12 +23,12 @@
 #include <error/expected_utils.h>
 
 #include "core-impl/StreamStub.h"
-#include "core-impl/StreamSwitcher.h"
+#include "deprecated/StreamSwitcher.h"
 
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::media::audio::common::AudioDevice;
 
-namespace aidl::android::hardware::audio::core {
+namespace aidl::android::hardware::audio::core::deprecated {
 
 StreamSwitcher::StreamSwitcher(StreamContext* context, const Metadata& metadata)
     : mContext(context),
@@ -260,4 +260,12 @@
     return mStream->bluetoothParametersUpdated();
 }
 
-}  // namespace aidl::android::hardware::audio::core
+ndk::ScopedAStatus StreamSwitcher::setGain(float gain) {
+    if (mStream == nullptr) {
+        LOG(ERROR) << __func__ << ": stream was closed";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    return mStream->setGain(gain);
+}
+
+}  // namespace aidl::android::hardware::audio::core::deprecated
diff --git a/audio/aidl/default/include/core-impl/StreamSwitcher.h b/audio/aidl/default/deprecated/StreamSwitcher.h
similarity index 95%
rename from audio/aidl/default/include/core-impl/StreamSwitcher.h
rename to audio/aidl/default/deprecated/StreamSwitcher.h
index 5764ad6..56fdd23 100644
--- a/audio/aidl/default/include/core-impl/StreamSwitcher.h
+++ b/audio/aidl/default/deprecated/StreamSwitcher.h
@@ -14,11 +14,18 @@
  * limitations under the License.
  */
 
+/**
+ ** This class is deprecated because its use causes threading issues
+ ** with the FMQ due to change of threads reading and writing into FMQ.
+ **
+ ** DO NOT USE. These files will be removed.
+ **/
+
 #pragma once
 
-#include "Stream.h"
+#include "core-impl/Stream.h"
 
-namespace aidl::android::hardware::audio::core {
+namespace aidl::android::hardware::audio::core::deprecated {
 
 // 'StreamSwitcher' is an implementation of 'StreamCommonInterface' which allows
 // dynamically switching the underlying stream implementation based on currently
@@ -130,6 +137,7 @@
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
             override;
     ndk::ScopedAStatus bluetoothParametersUpdated() override;
+    ndk::ScopedAStatus setGain(float gain) override;
 
   protected:
     // Since switching a stream requires closing down the current stream, StreamSwitcher
@@ -191,4 +199,4 @@
     bool mBluetoothParametersUpdated = false;
 };
 
-}  // namespace aidl::android::hardware::audio::core
+}  // namespace aidl::android::hardware::audio::core::deprecated
diff --git a/audio/aidl/default/eraser/Android.bp b/audio/aidl/default/eraser/Android.bp
new file mode 100644
index 0000000..c495d8e
--- /dev/null
+++ b/audio/aidl/default/eraser/Android.bp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_team: "trendy_team_android_media_audio_framework",
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_shared {
+    name: "liberasersw",
+    defaults: [
+        "aidlaudioeffectservice_defaults",
+    ],
+    srcs: [
+        "Eraser.cpp",
+        ":effectCommonFile",
+    ],
+    relative_install_path: "soundfx",
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default:__subpackages__",
+    ],
+}
diff --git a/audio/aidl/default/eraser/Eraser.cpp b/audio/aidl/default/eraser/Eraser.cpp
new file mode 100644
index 0000000..59cc9a2
--- /dev/null
+++ b/audio/aidl/default/eraser/Eraser.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_Eraser"
+
+#include "Eraser.h"
+
+#include <android-base/logging.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include <optional>
+
+using aidl::android::hardware::audio::common::getChannelCount;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EraserSw;
+using aidl::android::hardware::audio::effect::getEffectImplUuidEraserSw;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidEraser;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidEraserSw()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (!instanceSpp) {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+
+    *instanceSpp = ndk::SharedRefBase::make<EraserSw>();
+    LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+    return EX_NONE;
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidEraserSw()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    *_aidl_return = EraserSw::kDescriptor;
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string EraserSw::kEffectName = "EraserSw";
+const Descriptor EraserSw::kDescriptor = {
+        .common = {.id = {.type = getEffectTypeUuidEraser(), .uuid = getEffectImplUuidEraserSw()},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .hwAcceleratorMode = Flags::HardwareAccelerator::NONE},
+                   .name = EraserSw::kEffectName,
+                   .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus EraserSw::getDescriptor(Descriptor* _aidl_return) {
+    LOG(DEBUG) << __func__ << kDescriptor.toString();
+    *_aidl_return = kDescriptor;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EraserSw::setParameterSpecific(const Parameter::Specific& specific) {
+    RETURN_IF(Parameter::Specific::eraser != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+              "EffectNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto& param = specific.get<Parameter::Specific::eraser>();
+    return mContext->setParam(param.getTag(), param);
+}
+
+ndk::ScopedAStatus EraserSw::getParameterSpecific(const Parameter::Id& id,
+                                                  Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto tag = id.getTag();
+    RETURN_IF(Parameter::Id::eraserTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    auto eraserId = id.get<Parameter::Id::eraserTag>();
+    auto eraserTag = eraserId.getTag();
+    switch (eraserTag) {
+        case Eraser::Id::commonTag: {
+            auto specificTag = eraserId.get<Eraser::Id::commonTag>();
+            std::optional<Eraser> param = mContext->getParam(specificTag);
+            if (!param.has_value()) {
+                return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                        "EraserTagNotSupported");
+            }
+            specific->set<Parameter::Specific::eraser>(param.value());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "EraserTagNotSupported");
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> EraserSw::createContext(const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+    } else {
+        mContext = std::make_shared<EraserSwContext>(1 /* statusFmqDepth */, common);
+    }
+    return mContext;
+}
+
+RetCode EraserSw::releaseContext() {
+    if (mContext) {
+        mContext.reset();
+    }
+    return RetCode::SUCCESS;
+}
+
+EraserSw::~EraserSw() {
+    cleanUp();
+    LOG(DEBUG) << __func__;
+}
+
+ndk::ScopedAStatus EraserSw::command(CommandId command) {
+    std::lock_guard lg(mImplMutex);
+    RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "instanceNotOpen");
+
+    switch (command) {
+        case CommandId::START:
+            RETURN_OK_IF(mState == State::PROCESSING);
+            mState = State::PROCESSING;
+            mContext->enable();
+            startThread();
+            RETURN_IF(notifyEventFlag(mDataMqNotEmptyEf) != RetCode::SUCCESS, EX_ILLEGAL_STATE,
+                      "notifyEventFlagNotEmptyFailed");
+            break;
+        case CommandId::STOP:
+            RETURN_OK_IF(mState == State::IDLE || mState == State::DRAINING);
+            if (mVersion < kDrainSupportedVersion) {
+                mState = State::IDLE;
+                stopThread();
+                mContext->disable();
+            } else {
+                mState = State::DRAINING;
+                startDraining();
+                mContext->startDraining();
+            }
+            RETURN_IF(notifyEventFlag(mDataMqNotEmptyEf) != RetCode::SUCCESS, EX_ILLEGAL_STATE,
+                      "notifyEventFlagNotEmptyFailed");
+            break;
+        case CommandId::RESET:
+            mState = State::IDLE;
+            RETURN_IF(notifyEventFlag(mDataMqNotEmptyEf) != RetCode::SUCCESS, EX_ILLEGAL_STATE,
+                      "notifyEventFlagNotEmptyFailed");
+            stopThread();
+            mImplContext->disable();
+            mImplContext->reset();
+            mImplContext->resetBuffer();
+            break;
+        default:
+            LOG(ERROR) << getEffectNameWithVersion() << __func__ << " instance still processing";
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "CommandIdNotSupported");
+    }
+    LOG(VERBOSE) << getEffectNameWithVersion() << __func__
+                 << " transfer to state: " << toString(mState);
+    return ndk::ScopedAStatus::ok();
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status EraserSw::effectProcessImpl(float* in, float* out, int samples) {
+    RETURN_VALUE_IF(!mContext, (IEffect::Status{EX_NULL_POINTER, 0, 0}), "nullContext");
+    IEffect::Status procStatus{STATUS_NOT_ENOUGH_DATA, 0, 0};
+    procStatus = mContext->process(in, out, samples);
+    if (mState == State::DRAINING && procStatus.status == STATUS_NOT_ENOUGH_DATA) {
+        drainingComplete_l();
+    }
+
+    return procStatus;
+}
+
+void EraserSw::drainingComplete_l() {
+    if (mState != State::DRAINING) return;
+
+    LOG(DEBUG) << getEffectNameWithVersion() << __func__;
+    finishDraining();
+    mState = State::IDLE;
+}
+
+EraserSwContext::EraserSwContext(int statusDepth, const Parameter::Common& common)
+    : EffectContext(statusDepth, common) {
+    LOG(DEBUG) << __func__;
+}
+
+EraserSwContext::~EraserSwContext() {
+    LOG(DEBUG) << __func__;
+}
+
+template <typename TAG>
+std::optional<Eraser> EraserSwContext::getParam(TAG tag) {
+    if (mParamsMap.find(tag) != mParamsMap.end()) {
+        return mParamsMap.at(tag);
+    }
+    return std::nullopt;
+}
+
+template <typename TAG>
+ndk::ScopedAStatus EraserSwContext::setParam(TAG tag, Eraser eraser) {
+    mParamsMap[tag] = eraser;
+    return ndk::ScopedAStatus::ok();
+}
+
+IEffect::Status EraserSwContext::process(float* in, float* out, int samples) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    IEffect::Status procStatus = {EX_ILLEGAL_ARGUMENT, 0, 0};
+    const auto inputChannelCount = getChannelCount(mCommon.input.base.channelMask);
+    const auto outputChannelCount = getChannelCount(mCommon.output.base.channelMask);
+    if (inputChannelCount < outputChannelCount) {
+        LOG(ERROR) << __func__ << " invalid channel count, in: " << inputChannelCount
+                   << " out: " << outputChannelCount;
+        return procStatus;
+    }
+
+    if (samples <= 0 || 0 != samples % inputChannelCount) {
+        LOG(ERROR) << __func__ << " invalid samples: " << samples;
+        return procStatus;
+    }
+
+    const int iFrames = samples / inputChannelCount;
+    const float gainPerSample = 1.f / iFrames;
+    for (int i = 0; i < iFrames; i++) {
+        if (isDraining()) {
+            const float gain = (iFrames - i - 1) * gainPerSample;
+            for (size_t c = 0; c < outputChannelCount; c++) {
+                out[c] = in[c] * gain;
+            }
+        } else {
+            std::memcpy(out, in, outputChannelCount * sizeof(float));
+        }
+
+        in += inputChannelCount;
+        out += outputChannelCount;
+    }
+
+    // drain for one cycle
+    if (isDraining()) {
+        procStatus.status = STATUS_NOT_ENOUGH_DATA;
+        finishDraining();
+    } else {
+        procStatus.status = STATUS_OK;
+    }
+    procStatus.fmqConsumed = static_cast<int32_t>(iFrames * inputChannelCount);
+    procStatus.fmqProduced = static_cast<int32_t>(iFrames * outputChannelCount);
+
+    return procStatus;
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/eraser/Eraser.h b/audio/aidl/default/eraser/Eraser.h
new file mode 100644
index 0000000..7bf2f57
--- /dev/null
+++ b/audio/aidl/default/eraser/Eraser.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 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 "effect-impl/EffectContext.h"
+#include "effect-impl/EffectImpl.h"
+
+#include <fmq/AidlMessageQueue.h>
+
+#include <unordered_map>
+#include <vector>
+
+namespace aidl::android::hardware::audio::effect {
+
+class EraserSwContext final : public EffectContext {
+  public:
+    EraserSwContext(int statusDepth, const Parameter::Common& common);
+    ~EraserSwContext() final;
+
+    template <typename TAG>
+    std::optional<Eraser> getParam(TAG tag);
+    template <typename TAG>
+    ndk::ScopedAStatus setParam(TAG tag, Eraser eraser);
+
+    IEffect::Status process(float* in, float* out, int samples);
+
+  private:
+    std::unordered_map<Eraser::Tag, Eraser> mParamsMap;
+};
+
+class EraserSw final : public EffectImpl {
+  public:
+    static const std::string kEffectName;
+    static const Capability kCapability;
+    static const Descriptor kDescriptor;
+    ~EraserSw() final;
+
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) final;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
+            REQUIRES(mImplMutex) final;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
+            REQUIRES(mImplMutex) final;
+
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
+            REQUIRES(mImplMutex) final;
+    RetCode releaseContext() REQUIRES(mImplMutex) final;
+
+    std::string getEffectName() final { return kEffectName; };
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples)
+            REQUIRES(mImplMutex) final;
+
+    ndk::ScopedAStatus command(CommandId command) final;
+    void drainingComplete_l() REQUIRES(mImplMutex);
+
+  private:
+    static const std::vector<Range::SpatializerRange> kRanges;
+    std::shared_ptr<EraserSwContext> mContext GUARDED_BY(mImplMutex);
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/core-impl/CapEngineConfigXmlConverter.h b/audio/aidl/default/include/core-impl/CapEngineConfigXmlConverter.h
new file mode 100644
index 0000000..e5da4f4
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/CapEngineConfigXmlConverter.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/core/BnConfig.h>
+#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
+#include <system/audio_config.h>
+
+#include <android_audio_policy_capengine_configuration.h>
+#include <android_audio_policy_capengine_configuration_enums.h>
+
+#include "EngineConfigXmlConverter.h"
+
+namespace aidl::android::hardware::audio::core::internal {
+
+namespace capconfiguration = ::android::audio::policy::capengine::configuration;
+namespace aidlcommon = ::aidl::android::media::audio::common;
+
+class CapEngineConfigXmlConverter {
+  public:
+    explicit CapEngineConfigXmlConverter(const std::string& configFilePath)
+        : mConverter(configFilePath, &capconfiguration::readConfigurableDomains) {
+        if (mConverter.getXsdcConfig()) {
+            init();
+        }
+    }
+    std::string getError() const { return mConverter.getError(); }
+    ::android::status_t getStatus() const { return mConverter.getStatus(); }
+
+    std::optional<
+            std::vector<std::optional<::aidl::android::media::audio::common::AudioHalCapDomain>>>&
+    getAidlCapEngineConfig();
+
+  private:
+    ConversionResult<std::vector<aidlcommon::AudioHalCapParameter>> convertSettingToAidl(
+            const capconfiguration::SettingsType::Configuration& xsdcSetting);
+
+    ConversionResult<std::vector<aidlcommon::AudioHalCapConfiguration>> convertConfigurationsToAidl(
+            const std::vector<capconfiguration::ConfigurationsType>& xsdcConfigurationsVec,
+            const std::vector<capconfiguration::SettingsType>& xsdcSettingsVec);
+
+    ConversionResult<aidlcommon::AudioHalCapConfiguration> convertConfigurationToAidl(
+            const capconfiguration::ConfigurationsType::Configuration& xsdcConfiguration,
+            const capconfiguration::SettingsType::Configuration& xsdcSettingConfiguration);
+
+    ConversionResult<aidlcommon::AudioHalCapParameter> convertParamToAidl(
+            const capconfiguration::ConfigurableElementSettingsType& element);
+
+    ConversionResult<aidlcommon::AudioHalCapConfiguration> convertConfigurationToAidl(
+            const capconfiguration::ConfigurationsType::Configuration& xsdcConfiguration);
+    ConversionResult<aidlcommon::AudioHalCapDomain> convertConfigurableDomainToAidl(
+            const capconfiguration::ConfigurableDomainType& xsdcConfigurableDomain);
+
+    const std::optional<capconfiguration::ConfigurableDomains>& getXsdcConfig() {
+        return mConverter.getXsdcConfig();
+    }
+    void init();
+
+    std::optional<std::vector<std::optional<aidlcommon::AudioHalCapDomain>>> mAidlCapDomains;
+    XmlConverter<capconfiguration::ConfigurableDomains> mConverter;
+};
+}  // 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 22ac8cb..211c16f 100644
--- a/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h
+++ b/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h
@@ -59,6 +59,7 @@
     ConversionResult<::aidl::android::media::audio::common::AudioHalProductStrategy>
     convertProductStrategyToAidl(const ::android::audio::policy::engine::configuration::
                                          ProductStrategies::ProductStrategy& xsdcProductStrategy);
+    ConversionResult<int> convertProductStrategyIdToAidl(int xsdcId);
     ConversionResult<int> convertProductStrategyNameToAidl(
             const std::string& xsdcProductStrategyName);
     ConversionResult<::aidl::android::media::audio::common::AudioHalVolumeCurve>
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 00eeb4e..cbc13d1 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -148,8 +148,10 @@
     struct VendorDebug {
         static const std::string kForceTransientBurstName;
         static const std::string kForceSynchronousDrainName;
+        static const std::string kForceDrainToDrainingName;
         bool forceTransientBurst = false;
         bool forceSynchronousDrain = false;
+        bool forceDrainToDraining = false;
     };
     // ids of device ports created at runtime via 'connectExternalDevice'.
     // Also stores a list of ids of mix ports with dynamic profiles that were populated from
@@ -205,12 +207,15 @@
     virtual std::unique_ptr<Configuration> initializeConfig();
     virtual int32_t getNominalLatencyMs(
             const ::aidl::android::media::audio::common::AudioPortConfig& portConfig);
+    virtual ndk::ScopedAStatus calculateBufferSizeFrames(
+            const ::aidl::android::media::audio::common::AudioFormatDescription &format,
+            int32_t latencyMs, int32_t sampleRateHz, int32_t *bufferSizeFrames);
     virtual ndk::ScopedAStatus createMmapBuffer(
             const ::aidl::android::hardware::audio::core::StreamContext& context,
             ::aidl::android::hardware::audio::core::StreamDescriptor* desc);
 
     // Utility and helper functions accessible to subclasses.
-    static int32_t calculateBufferSizeFrames(int32_t latencyMs, int32_t sampleRateHz) {
+    static int32_t calculateBufferSizeFramesForPcm(int32_t latencyMs, int32_t sampleRateHz) {
         const int32_t rawSizeFrames =
                 aidl::android::hardware::audio::common::frameCountFromDurationMs(latencyMs,
                                                                                  sampleRateHz);
@@ -241,6 +246,8 @@
     std::vector<AudioRoute*> getAudioRoutesForAudioPortImpl(int32_t portId);
     Configuration& getConfig();
     const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
+    std::vector<::aidl::android::media::audio::common::AudioDevice>
+    getDevicesFromDevicePortConfigIds(const std::set<int32_t>& devicePortConfigIds);
     bool getMasterMute() const { return mMasterMute; }
     bool getMasterVolume() const { return mMasterVolume; }
     bool getMicMute() const { return mMicMute; }
@@ -263,6 +270,9 @@
             ::aidl::android::media::audio::common::AudioPortConfig* out_suggested, bool* applied);
     ndk::ScopedAStatus updateStreamsConnectedState(const AudioPatch& oldPatch,
                                                    const AudioPatch& newPatch);
+    bool setAudioPortConfigGain(
+            const ::aidl::android::media::audio::common::AudioPort& port,
+            const ::aidl::android::media::audio::common::AudioGainConfig& gainRequested);
 };
 
 std::ostream& operator<<(std::ostream& os, Module::Type t);
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 00f3af1..8297fc5 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -38,6 +38,7 @@
 #include <aidl/android/media/audio/common/AudioIoFlags.h>
 #include <aidl/android/media/audio/common/AudioOffloadInfo.h>
 #include <aidl/android/media/audio/common/MicrophoneInfo.h>
+#include <android-base/thread_annotations.h>
 #include <error/expected_utils.h>
 #include <fmq/AidlMessageQueue.h>
 #include <system/thread_defs.h>
@@ -77,6 +78,10 @@
         bool forceTransientBurst = false;
         // Force the "drain" command to be synchronous, going directly to the IDLE state.
         bool forceSynchronousDrain = false;
+        // Force the "drain early notify" command to keep the SM in the DRAINING state
+        // after sending 'onDrainReady' callback. The SM moves to IDLE after
+        // 'transientStateDelayMs'.
+        bool forceDrainToDraining = false;
     };
 
     StreamContext() = default;
@@ -118,6 +123,7 @@
     ::aidl::android::media::audio::common::AudioIoFlags getFlags() const { return mFlags; }
     bool getForceTransientBurst() const { return mDebugParameters.forceTransientBurst; }
     bool getForceSynchronousDrain() const { return mDebugParameters.forceSynchronousDrain; }
+    bool getForceDrainToDraining() const { return mDebugParameters.forceDrainToDraining; }
     size_t getFrameSize() const;
     int getInternalCommandCookie() const { return mInternalCommandCookie; }
     int32_t getMixPortHandle() const { return mMixPortHandle; }
@@ -300,6 +306,9 @@
     bool write(size_t clientSize, StreamDescriptor::Reply* reply);
 
     std::shared_ptr<IStreamOutEventCallback> mEventCallback;
+
+    enum OnDrainReadyStatus : int32_t { IGNORE /*used for DRAIN_ALL*/, UNSENT, SENT };
+    OnDrainReadyStatus mOnDrainReadyStatus = OnDrainReadyStatus::IGNORE;
 };
 using StreamOutWorker = StreamWorkerImpl<StreamOutWorkerLogic>;
 
@@ -345,6 +354,7 @@
     virtual ndk::ScopedAStatus setConnectedDevices(
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) = 0;
     virtual ndk::ScopedAStatus bluetoothParametersUpdated() = 0;
+    virtual ndk::ScopedAStatus setGain(float gain) = 0;
 };
 
 // This is equivalent to automatically generated 'IStreamCommonDelegator' but uses
@@ -446,6 +456,7 @@
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
             override;
     ndk::ScopedAStatus bluetoothParametersUpdated() override;
+    ndk::ScopedAStatus setGain(float gain) override;
 
   protected:
     static StreamWorkerInterface::CreateInstance getDefaultInWorkerCreator() {
@@ -612,6 +623,12 @@
         return ndk::ScopedAStatus::ok();
     }
 
+    ndk::ScopedAStatus setGain(float gain) {
+        auto s = mStream.lock();
+        if (s) return s->setGain(gain);
+        return ndk::ScopedAStatus::ok();
+    }
+
   private:
     std::weak_ptr<StreamCommonInterface> mStream;
     ndk::SpAIBinder mStreamBinder;
@@ -647,6 +664,12 @@
         return isOk ? ndk::ScopedAStatus::ok()
                     : ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
     }
+    ndk::ScopedAStatus setGain(int32_t portId, float gain) {
+        if (auto it = mStreams.find(portId); it != mStreams.end()) {
+            return it->second.setGain(gain);
+        }
+        return ndk::ScopedAStatus::ok();
+    }
 
   private:
     // Maps port ids and port config ids to streams. Multimap because a port
diff --git a/audio/aidl/default/include/core-impl/StreamAlsa.h b/audio/aidl/default/include/core-impl/StreamAlsa.h
index 0356946..8bdf208 100644
--- a/audio/aidl/default/include/core-impl/StreamAlsa.h
+++ b/audio/aidl/default/include/core-impl/StreamAlsa.h
@@ -45,6 +45,7 @@
                                  int32_t* latencyMs) override;
     ::android::status_t refinePosition(StreamDescriptor::Position* position) override;
     void shutdown() override;
+    ndk::ScopedAStatus setGain(float gain) override;
 
   protected:
     // Called from 'start' to initialize 'mAlsaDeviceProxies', the vector must be non-empty.
@@ -58,6 +59,9 @@
     const int mReadWriteRetries;
     // All fields below are only used on the worker thread.
     std::vector<alsa::DeviceProxy> mAlsaDeviceProxies;
+
+  private:
+    std::atomic<float> mGain = 1.0;
 };
 
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
index 6ea7968..5e52ad0 100644
--- a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
+++ b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
@@ -19,7 +19,7 @@
 #include <vector>
 
 #include "core-impl/Stream.h"
-#include "core-impl/StreamSwitcher.h"
+#include "deprecated/StreamSwitcher.h"
 #include "r_submix/SubmixRoute.h"
 
 namespace aidl::android::hardware::audio::core {
@@ -73,7 +73,7 @@
     int mWriteShutdownCount = 0;
 };
 
-class StreamInRemoteSubmix final : public StreamIn, public StreamSwitcher {
+class StreamInRemoteSubmix final : public StreamIn, public deprecated::StreamSwitcher {
   public:
     friend class ndk::SharedRefBase;
     StreamInRemoteSubmix(
@@ -85,7 +85,7 @@
     DeviceSwitchBehavior switchCurrentStream(
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
             override;
-    std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+    std::unique_ptr<deprecated::StreamCommonInterfaceEx> createNewStream(
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
             StreamContext* context, const Metadata& metadata) override;
     void onClose(StreamDescriptor::State) override { defaultOnClose(); }
@@ -94,7 +94,7 @@
             override;
 };
 
-class StreamOutRemoteSubmix final : public StreamOut, public StreamSwitcher {
+class StreamOutRemoteSubmix final : public StreamOut, public deprecated::StreamSwitcher {
   public:
     friend class ndk::SharedRefBase;
     StreamOutRemoteSubmix(
@@ -107,7 +107,7 @@
     DeviceSwitchBehavior switchCurrentStream(
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
             override;
-    std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+    std::unique_ptr<deprecated::StreamCommonInterfaceEx> createNewStream(
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
             StreamContext* context, const Metadata& metadata) override;
     void onClose(StreamDescriptor::State) override { defaultOnClose(); }
diff --git a/audio/aidl/default/include/core-impl/XmlConverter.h b/audio/aidl/default/include/core-impl/XmlConverter.h
index 68e6b8e..4b99d72 100644
--- a/audio/aidl/default/include/core-impl/XmlConverter.h
+++ b/audio/aidl/default/include/core-impl/XmlConverter.h
@@ -106,6 +106,19 @@
 }
 
 template <typename X, typename A>
+static ConversionResult<std::vector<std::optional<A>>> convertCollectionToAidlOptionalValues(
+        const std::vector<X>& xsdcTypeVec,
+        std::function<ConversionResult<A>(const X&)> convertToAidl) {
+    std::vector<std::optional<A>> resultAidlTypeVec;
+    resultAidlTypeVec.reserve(xsdcTypeVec.size());
+    for (const X& xsdcType : xsdcTypeVec) {
+        resultAidlTypeVec.push_back(
+                std::optional<A>(std::move(VALUE_OR_FATAL(convertToAidl(xsdcType)))));
+    }
+    return resultAidlTypeVec;
+}
+
+template <typename X, typename A>
 static ConversionResult<std::vector<A>> convertCollectionToAidl(
         const std::vector<X>& xsdcTypeVec,
         std::function<ConversionResult<A>(const X&)> convertToAidl) {
diff --git a/audio/aidl/default/include/core-impl/XsdcConversion.h b/audio/aidl/default/include/core-impl/XsdcConversion.h
index 30dc8b6..f00206b 100644
--- a/audio/aidl/default/include/core-impl/XsdcConversion.h
+++ b/audio/aidl/default/include/core-impl/XsdcConversion.h
@@ -1,9 +1,24 @@
+/*
+ * Copyright (C) 2024 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 <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/AudioHalCapCriterionV2.h>
 #include <aidl/android/media/audio/common/AudioHalVolumeCurve.h>
 #include <aidl/android/media/audio/common/AudioPort.h>
 #include <android_audio_policy_configuration.h>
@@ -15,15 +30,38 @@
 
 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);
+namespace engineconfiguration = ::android::audio::policy::engine::configuration;
+namespace aidlaudiocommon = ::aidl::android::media::audio::common;
+
+static constexpr const char kXsdcForceConfigForUse[] = "ForceUseFor";
+
+ConversionResult<aidlaudiocommon::AudioPolicyForceUse> convertForceUseToAidl(
+        const std::string& xsdcCriterionName, const std::string& xsdcCriterionValue);
+ConversionResult<aidlaudiocommon::AudioDeviceAddress> convertDeviceAddressToAidl(
+        const std::string& xsdcAddress);
+ConversionResult<aidlaudiocommon::AudioMode> convertTelephonyModeToAidl(
+        const std::string& xsdcModeCriterionType);
+ConversionResult<aidlaudiocommon::AudioDeviceDescription> convertDeviceTypeToAidl(
+        const std::string& xType);
+ConversionResult<std::vector<std::optional<aidlaudiocommon::AudioHalCapCriterionV2>>>
+convertCapCriteriaCollectionToAidl(
+        const std::vector<engineconfiguration::CriteriaType>& xsdcCriteriaVec,
+        const std::vector<engineconfiguration::CriterionTypesType>& xsdcCriterionTypesVec);
+ConversionResult<aidlaudiocommon::AudioHalCapCriterionV2> convertCapCriterionV2ToAidl(
+        const engineconfiguration::CriterionType& xsdcCriterion,
+        const std::vector<engineconfiguration::CriterionTypesType>& xsdcCriterionTypesVec);
+ConversionResult<aidlaudiocommon::AudioHalVolumeCurve::CurvePoint> convertCurvePointToAidl(
+        const std::string& xsdcCurvePoint);
 ConversionResult<std::unique_ptr<Module::Configuration>> convertModuleConfigToAidl(
         const ::android::audio::policy::configuration::Modules::Module& moduleConfig);
+ConversionResult<aidlaudiocommon::AudioUsage> convertAudioUsageToAidl(
+        const engineconfiguration::UsageEnumType& xsdcUsage);
+ConversionResult<aidlaudiocommon::AudioContentType> convertAudioContentTypeToAidl(
+        const engineconfiguration::ContentType& xsdcContentType);
+ConversionResult<aidlaudiocommon::AudioSource> convertAudioSourceToAidl(
+        const engineconfiguration::SourceEnumType& xsdcSourceType);
+ConversionResult<aidlaudiocommon::AudioStreamType> convertAudioStreamTypeToAidl(
+        const engineconfiguration::Stream& xsdStreamType);
+ConversionResult<int32_t> convertAudioFlagsToAidl(
+        const std::vector<engineconfiguration::FlagType>& xsdcFlagTypeVec);
 }  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/include/effect-impl/EffectContext.h b/audio/aidl/default/include/effect-impl/EffectContext.h
index 275378e..9e44349 100644
--- a/audio/aidl/default/include/effect-impl/EffectContext.h
+++ b/audio/aidl/default/include/effect-impl/EffectContext.h
@@ -82,7 +82,16 @@
 
     virtual ::android::hardware::EventFlag* getStatusEventFlag();
 
+    virtual RetCode enable();
+    virtual RetCode disable();
+    virtual RetCode reset();
+
+    virtual RetCode startDraining();
+    virtual RetCode finishDraining();
+    virtual bool isDraining();
+
   protected:
+    bool mIsDraining = false;
     int mVersion = 0;
     size_t mInputFrameSize = 0;
     size_t mOutputFrameSize = 0;
diff --git a/audio/aidl/default/include/effect-impl/EffectThread.h b/audio/aidl/default/include/effect-impl/EffectThread.h
index ec2a658..9abcdb8 100644
--- a/audio/aidl/default/include/effect-impl/EffectThread.h
+++ b/audio/aidl/default/include/effect-impl/EffectThread.h
@@ -38,6 +38,8 @@
     RetCode destroyThread();
     RetCode startThread();
     RetCode stopThread();
+    RetCode startDraining();
+    RetCode finishDraining();
 
     // Will call process() in a loop if the thread is running.
     void threadLoop();
@@ -49,6 +51,9 @@
      */
     virtual void process() = 0;
 
+  protected:
+    bool mDraining GUARDED_BY(mThreadMutex) = false;
+
   private:
     static constexpr int kMaxTaskNameLen = 15;
 
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectConfig.h b/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
index 7456b99..60bb9be 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
@@ -81,7 +81,7 @@
     /* Parsed Effects result */
     std::unordered_map<std::string, struct EffectLibraries> mEffectsMap;
     /**
-     * For parsed pre/post processing result: {key: AudioStreamType/AudioSource, value:
+     * For parsed pre/post processing result: {key: AudioStreamType/AudioSource/AudioDevice, value:
      * EffectLibraries}
      */
     ProcessingLibrariesMap mProcessingMap;
@@ -110,7 +110,8 @@
     bool resolveLibrary(const std::string& path, std::string* resolvedPath);
 
     std::optional<Processing::Type> stringToProcessingType(Processing::Type::Tag typeTag,
-                                                           const std::string& type);
+                                                           const std::string& type,
+                                                           const std::string& address);
 };
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/main.cpp b/audio/aidl/default/main.cpp
index 6ab747d..0b3e3ba 100644
--- a/audio/aidl/default/main.cpp
+++ b/audio/aidl/default/main.cpp
@@ -71,6 +71,7 @@
     // For more logs, use VERBOSE, however this may hinder performance.
     // android::base::SetMinimumLogSeverity(::android::base::VERBOSE);
     ABinderProcess_setThreadPoolMaxThreadCount(16);
+    ABinderProcess_startThreadPool();
 
     // Guaranteed log for b/210919187 and logd_integration_test
     LOG(INFO) << "Init for Audio AIDL HAL";
diff --git a/audio/aidl/default/primary/StreamPrimary.cpp b/audio/aidl/default/primary/StreamPrimary.cpp
index 9fb07e5..46e384e 100644
--- a/audio/aidl/default/primary/StreamPrimary.cpp
+++ b/audio/aidl/default/primary/StreamPrimary.cpp
@@ -15,7 +15,11 @@
  */
 
 #define LOG_TAG "AHAL_StreamPrimary"
+
+#include <cstdio>
+
 #include <android-base/logging.h>
+#include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <audio_utils/clock.h>
 #include <error/Result.h>
@@ -26,6 +30,7 @@
 using aidl::android::hardware::audio::common::SinkMetadata;
 using aidl::android::hardware::audio::common::SourceMetadata;
 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::AudioOffloadInfo;
@@ -51,7 +56,9 @@
 }
 
 ::android::status_t StreamPrimary::flush() {
-    return isStubStreamOnWorker() ? mStubDriver.flush() : StreamAlsa::flush();
+    RETURN_STATUS_IF_ERROR(isStubStreamOnWorker() ? mStubDriver.flush() : StreamAlsa::flush());
+    // TODO(b/372951987): consider if this needs to be done from 'StreamInWorkerLogic::cycle'.
+    return mIsInput ? standby() : ::android::OK;
 }
 
 ::android::status_t StreamPrimary::pause() {
@@ -167,8 +174,22 @@
 }
 
 // static
-StreamPrimary::AlsaDeviceId StreamPrimary::getCardAndDeviceId(const std::vector<AudioDevice>&) {
-    return kDefaultCardAndDeviceId;
+StreamPrimary::AlsaDeviceId StreamPrimary::getCardAndDeviceId(
+        const std::vector<AudioDevice>& devices) {
+    if (devices.empty() || devices[0].address.getTag() != AudioDeviceAddress::id) {
+        return kDefaultCardAndDeviceId;
+    }
+    std::string deviceAddress = devices[0].address.get<AudioDeviceAddress::id>();
+    AlsaDeviceId cardAndDeviceId;
+    if (const size_t suffixPos = deviceAddress.rfind("CARD_");
+        suffixPos == std::string::npos ||
+        sscanf(deviceAddress.c_str() + suffixPos, "CARD_%d_DEV_%d", &cardAndDeviceId.first,
+               &cardAndDeviceId.second) != 2) {
+        return kDefaultCardAndDeviceId;
+    }
+    LOG(DEBUG) << __func__ << ": parsed with card id " << cardAndDeviceId.first << ", device id "
+               << cardAndDeviceId.second;
+    return cardAndDeviceId;
 }
 
 // static
@@ -181,12 +202,10 @@
     if (isInput) {
         return kSimulateInput || device.type.type == AudioDeviceType::IN_TELEPHONY_RX ||
                device.type.type == AudioDeviceType::IN_FM_TUNER ||
-               device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated */ ||
-               (device.type.type == AudioDeviceType::IN_BUS && device.type.connection.empty());
+               device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated */;
     }
     return kSimulateOutput || device.type.type == AudioDeviceType::OUT_TELEPHONY_TX ||
-           device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated*/ ||
-           (device.type.type == AudioDeviceType::OUT_BUS && device.type.connection.empty());
+           device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated*/;
 }
 
 StreamInPrimary::StreamInPrimary(StreamContext&& context, const SinkMetadata& sinkMetadata,
@@ -199,11 +218,12 @@
     if (isStubStream()) {
         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
     }
-    float gain;
-    RETURN_STATUS_IF_ERROR(primary::PrimaryMixer::getInstance().getMicGain(&gain));
-    _aidl_return->resize(0);
-    _aidl_return->resize(mChannelCount, gain);
-    RETURN_STATUS_IF_ERROR(setHwGainImpl(*_aidl_return));
+    if (mHwGains.empty()) {
+        float gain;
+        RETURN_STATUS_IF_ERROR(primary::PrimaryMixer::getInstance().getMicGain(&gain));
+        _aidl_return->resize(mChannelCount, gain);
+        RETURN_STATUS_IF_ERROR(setHwGainImpl(*_aidl_return));
+    }
     return getHwGainImpl(_aidl_return);
 }
 
@@ -222,6 +242,14 @@
         mHwGains = currentGains;
         return status;
     }
+    float gain;
+    RETURN_STATUS_IF_ERROR(primary::PrimaryMixer::getInstance().getMicGain(&gain));
+    // Due to rounding errors, round trip conversions between percents and indexed values may not
+    // match.
+    if (gain != in_channelGains[0]) {
+        LOG(WARNING) << __func__ << ": unmatched gain: set: " << in_channelGains[0]
+                     << ", from mixer: " << gain;
+    }
     return ndk::ScopedAStatus::ok();
 }
 
@@ -235,9 +263,11 @@
     if (isStubStream()) {
         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
     }
-    RETURN_STATUS_IF_ERROR(primary::PrimaryMixer::getInstance().getVolumes(_aidl_return));
-    _aidl_return->resize(mChannelCount);
-    RETURN_STATUS_IF_ERROR(setHwVolumeImpl(*_aidl_return));
+    if (mHwVolumes.empty()) {
+        RETURN_STATUS_IF_ERROR(primary::PrimaryMixer::getInstance().getVolumes(_aidl_return));
+        _aidl_return->resize(mChannelCount);
+        RETURN_STATUS_IF_ERROR(setHwVolumeImpl(*_aidl_return));
+    }
     return getHwVolumeImpl(_aidl_return);
 }
 
@@ -253,6 +283,15 @@
         mHwVolumes = currentVolumes;
         return status;
     }
+    std::vector<float> volumes;
+    RETURN_STATUS_IF_ERROR(primary::PrimaryMixer::getInstance().getVolumes(&volumes));
+    // Due to rounding errors, round trip conversions between percents and indexed values may not
+    // match.
+    if (volumes != in_channelVolumes) {
+        LOG(WARNING) << __func__ << ": unmatched volumes: set: "
+                     << ::android::internal::ToString(in_channelVolumes)
+                     << ", from mixer: " << ::android::internal::ToString(volumes);
+    }
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
index 28b633c..cef0ea6 100644
--- a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
@@ -32,6 +32,10 @@
 
 namespace aidl::android::hardware::audio::core {
 
+using deprecated::InnerStreamWrapper;
+using deprecated::StreamCommonInterfaceEx;
+using deprecated::StreamSwitcher;
+
 StreamRemoteSubmix::StreamRemoteSubmix(StreamContext* context, const Metadata& metadata,
                                        const AudioDeviceAddress& deviceAddress)
     : StreamCommonImpl(context, metadata),
@@ -73,17 +77,15 @@
 }
 
 ::android::status_t StreamRemoteSubmix::drain(StreamDescriptor::DrainMode) {
-    usleep(1000);
     return ::android::OK;
 }
 
 ::android::status_t StreamRemoteSubmix::flush() {
-    usleep(1000);
-    return ::android::OK;
+    // TODO(b/372951987): consider if this needs to be done from 'StreamInWorkerLogic::cycle'.
+    return mIsInput ? standby() : ::android::OK;
 }
 
 ::android::status_t StreamRemoteSubmix::pause() {
-    usleep(1000);
     return ::android::OK;
 }
 
@@ -289,9 +291,12 @@
     char* buff = (char*)buffer;
     size_t actuallyRead = 0;
     long remainingFrames = frameCount;
-    const int64_t deadlineTimeNs =
-            ::android::uptimeNanos() +
-            getDelayInUsForFrameCount(frameCount) * NANOS_PER_MICROSECOND / 2;
+    // Try to wait as long as possible for the audio duration, but leave some time for the call to
+    // 'transfer' to complete. 'kReadAttemptSleepUs' is a good constant for this purpose because it
+    // is by definition "strictly inferior" to the typical buffer duration.
+    const long durationUs =
+            std::max(0L, getDelayInUsForFrameCount(frameCount) - kReadAttemptSleepUs);
+    const int64_t deadlineTimeNs = ::android::uptimeNanos() + durationUs * NANOS_PER_MICROSECOND;
     while (remainingFrames > 0) {
         ssize_t framesRead = source->read(buff, remainingFrames);
         LOG(VERBOSE) << __func__ << ": frames read " << framesRead;
diff --git a/audio/aidl/default/r_submix/SubmixRoute.cpp b/audio/aidl/default/r_submix/SubmixRoute.cpp
index 325a012..445b1d3 100644
--- a/audio/aidl/default/r_submix/SubmixRoute.cpp
+++ b/audio/aidl/default/r_submix/SubmixRoute.cpp
@@ -134,10 +134,10 @@
 // - the peer input is in standby AFTER having been active.
 // We DO block if:
 // - the input was never activated to avoid discarding first frames in the pipe in case capture
-// start was delayed
+//   start was delayed
 bool SubmixRoute::shouldBlockWrite() {
     std::lock_guard guard(mLock);
-    return (mStreamInOpen || (mStreamInStandby && (mReadCounterFrames != 0)));
+    return mStreamInOpen && (!mStreamInStandby || mReadCounterFrames == 0);
 }
 
 long SubmixRoute::updateReadCounterFrames(size_t frameCount) {
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index cbd42c0..5f0a608 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -14,6 +14,7 @@
         "latest_android_hardware_audio_common_ndk_static",
         "latest_android_hardware_audio_effect_ndk_static",
         "latest_android_media_audio_common_types_ndk_static",
+        "latest_android_media_audio_eraser_types_ndk_static",
         "use_libaidlvintf_gtest_helper_static",
         "VtsHalTargetTestDefaults",
     ],
@@ -115,6 +116,9 @@
     defaults: ["VtsHalAudioEffectTargetTestDefaults"],
     static_libs: ["libaudioaidlranges"],
     srcs: ["VtsHalDynamicsProcessingTest.cpp"],
+    shared_libs: [
+        "libaudioutils",
+    ],
 }
 
 cc_test {
@@ -136,6 +140,9 @@
     name: "VtsHalHapticGeneratorTargetTest",
     defaults: ["VtsHalAudioEffectTargetTestDefaults"],
     srcs: ["VtsHalHapticGeneratorTargetTest.cpp"],
+    shared_libs: [
+        "libaudioutils",
+    ],
 }
 
 cc_test {
@@ -166,6 +173,9 @@
     name: "VtsHalVisualizerTargetTest",
     defaults: ["VtsHalAudioEffectTargetTestDefaults"],
     srcs: ["VtsHalVisualizerTargetTest.cpp"],
+    shared_libs: [
+        "libaudioutils",
+    ],
 }
 
 cc_test {
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
index a081cfb..754a08f 100644
--- a/audio/aidl/vts/EffectHelper.h
+++ b/audio/aidl/vts/EffectHelper.h
@@ -84,6 +84,11 @@
     return prefix;
 }
 
+static constexpr float kMaxAudioSampleValue = 1;
+static constexpr int kNPointFFT = 16384;
+static constexpr int kSamplingFrequency = 44100;
+static constexpr int kDefaultChannelLayout = AudioChannelLayout::LAYOUT_STEREO;
+
 class EffectHelper {
   public:
     void create(std::shared_ptr<IFactory> factory, std::shared_ptr<IEffect>& effect,
@@ -122,7 +127,7 @@
             return;
         }
 
-        ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+        ASSERT_TRUE(expectState(effect, State::IDLE));
         updateFrameSize(common);
     }
 
@@ -153,7 +158,7 @@
         if (effect) {
             ASSERT_STATUS(status, effect->close());
             if (status == EX_NONE) {
-                ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
+                ASSERT_TRUE(expectState(effect, State::INIT));
             }
         }
     }
@@ -164,12 +169,14 @@
         ASSERT_STATUS(status, effect->getDescriptor(&desc));
     }
 
-    static void expectState(std::shared_ptr<IEffect> effect, State expectState,
-                            binder_status_t status = EX_NONE) {
-        ASSERT_NE(effect, nullptr);
-        State state;
-        ASSERT_STATUS(status, effect->getState(&state));
-        ASSERT_EQ(expectState, state);
+    static bool expectState(std::shared_ptr<IEffect> effect, State expectState) {
+        if (effect == nullptr) return false;
+
+        if (State state; EX_NONE != effect->getState(&state).getStatus() || expectState != state) {
+            return false;
+        }
+
+        return true;
     }
 
     static void commandIgnoreRet(std::shared_ptr<IEffect> effect, CommandId command) {
@@ -188,16 +195,17 @@
 
         switch (command) {
             case CommandId::START:
-                ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+                ASSERT_TRUE(expectState(effect, State::PROCESSING));
                 break;
             case CommandId::STOP:
                 // Enforce the state checking after kDrainSupportedVersion
                 if (getHalVersion(effect) >= kDrainSupportedVersion) {
-                    ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+                    ASSERT_TRUE(expectState(effect, State::IDLE) ||
+                                expectState(effect, State::DRAINING));
                 }
                 break;
             case CommandId::RESET:
-                ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+                ASSERT_TRUE(expectState(effect, State::IDLE));
                 break;
             default:
                 return;
@@ -253,13 +261,14 @@
         EXPECT_TRUE(efState & kEventFlagDataMqUpdate);
     }
 
-    Parameter::Common createParamCommon(int session = 0, int ioHandle = -1, int iSampleRate = 48000,
-                                        int oSampleRate = 48000, long iFrameCount = 0x100,
-                                        long oFrameCount = 0x100) {
-        AudioChannelLayout inputLayout = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
-                AudioChannelLayout::LAYOUT_STEREO);
-        AudioChannelLayout outputLayout = inputLayout;
-
+    Parameter::Common createParamCommon(
+            int session = 0, int ioHandle = -1, int iSampleRate = 48000, int oSampleRate = 48000,
+            long iFrameCount = 0x100, long oFrameCount = 0x100,
+            AudioChannelLayout inputChannelLayout =
+                    AudioChannelLayout::make<AudioChannelLayout::layoutMask>(kDefaultChannelLayout),
+            AudioChannelLayout outputChannelLayout =
+                    AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                            kDefaultChannelLayout)) {
         // query supported input layout and use it as the default parameter in common
         if (mIsSpatializer && isRangeValid<Range::spatializer>(Spatializer::supportedChannelLayout,
                                                                mDescriptor.capability)) {
@@ -269,18 +278,10 @@
                 layoutRange &&
                 0 != (layouts = layoutRange->min.get<Spatializer::supportedChannelLayout>())
                                 .size()) {
-                inputLayout = layouts[0];
+                inputChannelLayout = layouts[0];
             }
         }
 
-        return createParamCommon(session, ioHandle, iSampleRate, oSampleRate, iFrameCount,
-                                 oFrameCount, inputLayout, outputLayout);
-    }
-
-    static Parameter::Common createParamCommon(int session, int ioHandle, int iSampleRate,
-                                               int oSampleRate, long iFrameCount, long oFrameCount,
-                                               AudioChannelLayout inputChannelLayout,
-                                               AudioChannelLayout outputChannelLayout) {
         Parameter::Common common;
         common.session = session;
         common.ioHandle = ioHandle;
@@ -373,11 +374,30 @@
         return functor(result);
     }
 
+    // keep writing data to the FMQ until effect transit from DRAINING to IDLE
+    static void waitForDrain(std::vector<float>& inputBuffer, std::vector<float>& outputBuffer,
+                             const std::shared_ptr<IEffect>& effect,
+                             std::unique_ptr<EffectHelper::StatusMQ>& statusMQ,
+                             std::unique_ptr<EffectHelper::DataMQ>& inputMQ,
+                             std::unique_ptr<EffectHelper::DataMQ>& outputMQ, int version) {
+        State state;
+        while (effect->getState(&state).getStatus() == EX_NONE && state == State::DRAINING) {
+            EXPECT_NO_FATAL_FAILURE(
+                    EffectHelper::writeToFmq(statusMQ, inputMQ, inputBuffer, version));
+            EXPECT_NO_FATAL_FAILURE(EffectHelper::readFromFmq(
+                    statusMQ, 1, outputMQ, outputBuffer.size(), outputBuffer, std::nullopt));
+        }
+        ASSERT_TRUE(State::IDLE == state);
+        EXPECT_NO_FATAL_FAILURE(EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, outputBuffer));
+        return;
+    }
+
     static void processAndWriteToOutput(std::vector<float>& inputBuffer,
                                         std::vector<float>& outputBuffer,
                                         const std::shared_ptr<IEffect>& effect,
                                         IEffect::OpenEffectReturn* openEffectReturn,
-                                        int version = -1, int times = 1) {
+                                        int version = -1, int times = 1,
+                                        bool callStopReset = true) {
         // Initialize AidlMessagequeues
         auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(openEffectReturn->statusMQ);
         ASSERT_TRUE(statusMQ->isValid());
@@ -402,11 +422,16 @@
                                                               outputBuffer.size(), outputBuffer));
         }
 
-        ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
-        EXPECT_NO_FATAL_FAILURE(EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, outputBuffer));
-
         // Disable the process
-        ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
+        if (callStopReset) {
+            ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+            EXPECT_NO_FATAL_FAILURE(waitForDrain(inputBuffer, outputBuffer, effect, statusMQ,
+                                                 inputMQ, outputMQ, version));
+        }
+
+        if (callStopReset) {
+            ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
+        }
     }
 
     // Find FFT bin indices for testFrequencies and get bin center frequencies
@@ -418,36 +443,135 @@
         }
     }
 
-    // Generate multitone input between -1 to +1 using testFrequencies
-    void generateMultiTone(const std::vector<int>& testFrequencies, std::vector<float>& input,
-                           const int samplingFrequency) {
-        for (size_t i = 0; i < input.size(); i++) {
+    // Fill inputBuffer with random values between -maxAudioSampleValue to maxAudioSampleValue
+    void generateInputBuffer(std::vector<float>& inputBuffer, size_t startPosition, bool isStrip,
+                             size_t channelCount,
+                             float maxAudioSampleValue = kMaxAudioSampleValue) {
+        size_t increment = isStrip ? 1 /*Fill input at all the channels*/
+                                   : channelCount /*Fill input at only one channel*/;
+
+        for (size_t i = startPosition; i < inputBuffer.size(); i += increment) {
+            inputBuffer[i] =
+                    ((static_cast<float>(std::rand()) / RAND_MAX) * 2 - 1) * maxAudioSampleValue;
+        }
+    }
+
+    // Generate multitone input between -amplitude to +amplitude using testFrequencies
+    // All test frequencies are considered having the same amplitude
+    // The function supports only mono and stereo channel layout
+    void generateSineWave(const std::vector<int>& testFrequencies, std::vector<float>& input,
+                          const float amplitude = 1.0,
+                          const int samplingFrequency = kSamplingFrequency,
+                          int channelLayout = AudioChannelLayout::LAYOUT_STEREO) {
+        bool isStereo = (channelLayout == AudioChannelLayout::LAYOUT_STEREO);
+        if (isStereo) {
+            ASSERT_EQ(input.size() % 2, 0u)
+                    << "In case of stereo input, the input size value must be even";
+        }
+        for (size_t i = 0; i < input.size(); i += (isStereo ? 2 : 1)) {
             input[i] = 0;
 
             for (size_t j = 0; j < testFrequencies.size(); j++) {
-                input[i] += sin(2 * M_PI * testFrequencies[j] * i / samplingFrequency);
+                input[i] += sin(2 * M_PI * testFrequencies[j] * (i / (isStereo ? 2 : 1)) /
+                                samplingFrequency);
             }
-            input[i] /= testFrequencies.size();
+            input[i] *= amplitude / testFrequencies.size();
+
+            if (isStereo) {
+                input[i + 1] = input[i];
+            }
         }
     }
 
+    // Generate single tone input between -amplitude to +amplitude using testFrequency
+    // The function supports only mono and stereo channel layout
+    void generateSineWave(const int testFrequency, std::vector<float>& input,
+                          const float amplitude = 1.0,
+                          const int samplingFrequency = kSamplingFrequency,
+                          int channelLayout = AudioChannelLayout::LAYOUT_STEREO) {
+        ASSERT_NO_FATAL_FAILURE(generateSineWave(std::vector<int>{testFrequency}, input, amplitude,
+                                                 samplingFrequency, channelLayout));
+    }
+
+    // PFFFT only supports transforms for inputs of length N of the form N = (2^a)*(3^b)*(5^c) where
+    // a >= 5, b >=0, c >= 0.
+    constexpr bool isFftInputSizeValid(size_t n) {
+        if (n == 0 || n & 0b11111) {
+            return false;
+        }
+        for (const int factor : {2, 3, 5}) {
+            while (n % factor == 0) {
+                n /= factor;
+            }
+        }
+        return n == 1;
+    }
+
     // Use FFT transform to convert the buffer to frequency domain
     // Compute its magnitude at binOffsets
-    std::vector<float> calculateMagnitude(const std::vector<float>& buffer,
-                                          const std::vector<int>& binOffsets, const int nPointFFT) {
+    void calculateMagnitudeMono(std::vector<float>& bufferMag,       // Output parameter
+                                const std::vector<float>& buffer,    // Input parameter
+                                const std::vector<int>& binOffsets,  // Input parameter
+                                const int nPointFFT = kNPointFFT) {  // Input parameter
+        ASSERT_TRUE(isFftInputSizeValid(nPointFFT))
+                << "PFFFT only supports transforms for inputs of length N of the form N = (2 ^ a) "
+                   "* (3 ^ b) * (5 ^ c) where a >= 5, b >= 0, c >= 0. ";
+        ASSERT_GE((int)buffer.size(), nPointFFT)
+                << "The input(buffer) size must be greater than or equal to nPointFFT";
+        bufferMag.resize(binOffsets.size());
         std::vector<float> fftInput(nPointFFT);
         PFFFT_Setup* inputHandle = pffft_new_setup(nPointFFT, PFFFT_REAL);
         pffft_transform_ordered(inputHandle, buffer.data(), fftInput.data(), nullptr,
                                 PFFFT_FORWARD);
         pffft_destroy_setup(inputHandle);
-        std::vector<float> bufferMag(binOffsets.size());
         for (size_t i = 0; i < binOffsets.size(); i++) {
             size_t k = binOffsets[i];
             bufferMag[i] = sqrt((fftInput[k * 2] * fftInput[k * 2]) +
                                 (fftInput[k * 2 + 1] * fftInput[k * 2 + 1]));
         }
+    }
 
-        return bufferMag;
+    // Use FFT transform to convert the buffer to frequency domain
+    // Compute its magnitude at binOffsets
+    void calculateMagnitudeStereo(
+            std::pair<std::vector<float>, std::vector<float>>& bufferMag,  // Output parameter
+            const std::vector<float>& buffer,                              // Input parameter
+            const std::vector<int>& binOffsets,                            // Input parameter
+            const int nPointFFT = kNPointFFT) {                            // Input parameter
+        std::vector<float> leftChannelBuffer(buffer.size() / 2),
+                rightChannelBuffer(buffer.size() / 2);
+        for (size_t i = 0; i < buffer.size(); i += 2) {
+            leftChannelBuffer[i / 2] = buffer[i];
+            rightChannelBuffer[i / 2] = buffer[i + 1];
+        }
+        std::vector<float> leftMagnitude(binOffsets.size());
+        std::vector<float> rightMagnitude(binOffsets.size());
+
+        ASSERT_NO_FATAL_FAILURE(
+                calculateMagnitudeMono(leftMagnitude, leftChannelBuffer, binOffsets, nPointFFT));
+        ASSERT_NO_FATAL_FAILURE(
+                calculateMagnitudeMono(rightMagnitude, rightChannelBuffer, binOffsets, nPointFFT));
+
+        bufferMag = {leftMagnitude, rightMagnitude};
+    }
+
+    // Computes magnitude for mono and stereo inputs and verifies equal magnitude for left and right
+    // channel in case of stereo inputs
+    void calculateAndVerifyMagnitude(std::vector<float>& mag,             // Output parameter
+                                     const int channelLayout,             // Input parameter
+                                     const std::vector<float>& buffer,    // Input parameter
+                                     const std::vector<int>& binOffsets,  // Input parameter
+                                     const int nPointFFT = kNPointFFT) {  // Input parameter
+        if (channelLayout == AudioChannelLayout::LAYOUT_STEREO) {
+            std::pair<std::vector<float>, std::vector<float>> magStereo;
+            ASSERT_NO_FATAL_FAILURE(
+                    calculateMagnitudeStereo(magStereo, buffer, binOffsets, nPointFFT));
+            ASSERT_EQ(magStereo.first, magStereo.second);
+
+            mag = magStereo.first;
+        } else {
+            ASSERT_NO_FATAL_FAILURE(calculateMagnitudeMono(mag, buffer, binOffsets, nPointFFT));
+        }
     }
 
     void updateFrameSize(const Parameter::Common& common) {
@@ -459,6 +583,17 @@
         mOutputSamples = common.output.frameCount * mOutputFrameSize / sizeof(float);
     }
 
+    void generateInput(std::vector<float>& input, float inputFrequency, float samplingFrequency,
+                       size_t inputSize = 0) {
+        if (inputSize == 0 || inputSize > input.size()) {
+            inputSize = input.size();
+        }
+
+        for (size_t i = 0; i < inputSize; i++) {
+            input[i] = sin(2 * M_PI * inputFrequency * i / samplingFrequency);
+        }
+    }
+
     static int getHalVersion(const std::shared_ptr<IEffect>& effect) {
         int version = 0;
         return (effect && effect->getInterfaceVersion(&version).isOk()) ? version : 0;
diff --git a/audio/aidl/vts/VtsHalAECTargetTest.cpp b/audio/aidl/vts/VtsHalAECTargetTest.cpp
index 53b6757..c007f18 100644
--- a/audio/aidl/vts/VtsHalAECTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAECTargetTest.cpp
@@ -139,12 +139,12 @@
 };
 
 TEST_P(AECParamTest, SetAndGetEchoDelay) {
-    EXPECT_NO_FATAL_FAILURE(addEchoDelayParam(mEchoDelay));
+    addEchoDelayParam(mEchoDelay);
     SetAndGetParameters();
 }
 
 TEST_P(AECParamTest, SetAndGetMobileMode) {
-    EXPECT_NO_FATAL_FAILURE(addMobileModeParam(mMobileMode));
+    addMobileModeParam(mMobileMode);
     SetAndGetParameters();
 }
 
diff --git a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
index f14afbc..72a2d5e 100644
--- a/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC1TargetTest.cpp
@@ -139,17 +139,17 @@
 };
 
 TEST_P(AGC1ParamTest, SetAndGetTargetPeakLevelParam) {
-    EXPECT_NO_FATAL_FAILURE(addTargetPeakLevelParam(mTargetPeakLevel));
+    addTargetPeakLevelParam(mTargetPeakLevel);
     SetAndGetParameters();
 }
 
 TEST_P(AGC1ParamTest, SetAndGetMaxCompressionGain) {
-    EXPECT_NO_FATAL_FAILURE(addMaxCompressionGainParam(mMaxCompressionGain));
+    addMaxCompressionGainParam(mMaxCompressionGain);
     SetAndGetParameters();
 }
 
 TEST_P(AGC1ParamTest, SetAndGetEnableLimiter) {
-    EXPECT_NO_FATAL_FAILURE(addEnableLimiterParam(mEnableLimiter));
+    addEnableLimiterParam(mEnableLimiter);
     SetAndGetParameters();
 }
 
diff --git a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
index 048d540..ccac8c5 100644
--- a/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAGC2TargetTest.cpp
@@ -145,17 +145,17 @@
 };
 
 TEST_P(AGC2ParamTest, SetAndGetDigitalGainParam) {
-    EXPECT_NO_FATAL_FAILURE(addDigitalGainParam(mGain));
+    addDigitalGainParam(mGain);
     SetAndGetParameters();
 }
 
 TEST_P(AGC2ParamTest, SetAndGetSaturationMargin) {
-    EXPECT_NO_FATAL_FAILURE(addSaturationMarginParam(mMargin));
+    addSaturationMarginParam(mMargin);
     SetAndGetParameters();
 }
 
 TEST_P(AGC2ParamTest, SetAndGetLevelEstimator) {
-    EXPECT_NO_FATAL_FAILURE(addLevelEstimatorParam(mLevelEstimator));
+    addLevelEstimatorParam(mLevelEstimator);
     SetAndGetParameters();
 }
 
diff --git a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
index f82e8e5..eaec88b 100644
--- a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
@@ -38,16 +38,23 @@
 using aidl::android::hardware::audio::core::IConfig;
 using aidl::android::hardware::audio::core::SurroundSoundConfig;
 using aidl::android::media::audio::common::AudioAttributes;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+using aidl::android::media::audio::common::AudioDeviceDescription;
 using aidl::android::media::audio::common::AudioFlag;
 using aidl::android::media::audio::common::AudioFormatDescription;
 using aidl::android::media::audio::common::AudioFormatType;
 using aidl::android::media::audio::common::AudioHalAttributesGroup;
-using aidl::android::media::audio::common::AudioHalCapCriterion;
-using aidl::android::media::audio::common::AudioHalCapCriterionType;
+using aidl::android::media::audio::common::AudioHalCapConfiguration;
+using aidl::android::media::audio::common::AudioHalCapCriterionV2;
+using aidl::android::media::audio::common::AudioHalCapDomain;
+using aidl::android::media::audio::common::AudioHalCapParameter;
+using aidl::android::media::audio::common::AudioHalCapRule;
 using aidl::android::media::audio::common::AudioHalEngineConfig;
 using aidl::android::media::audio::common::AudioHalProductStrategy;
 using aidl::android::media::audio::common::AudioHalVolumeCurve;
 using aidl::android::media::audio::common::AudioHalVolumeGroup;
+using aidl::android::media::audio::common::AudioMode;
+using aidl::android::media::audio::common::AudioPolicyForceUse;
 using aidl::android::media::audio::common::AudioProductStrategyType;
 using aidl::android::media::audio::common::AudioSource;
 using aidl::android::media::audio::common::AudioStreamType;
@@ -256,48 +263,334 @@
     }
 
     /**
-     * Verify defaultLiteralValue is empty for inclusive criterion.
+     * Verify criterion provides a non empty value list.
+     * Verify logic rule provided is the expected one.
      */
-    void ValidateAudioHalCapCriterion(const AudioHalCapCriterion& criterion,
-                                      const AudioHalCapCriterionType& criterionType) {
-        if (criterionType.isInclusive) {
-            EXPECT_TRUE(criterion.defaultLiteralValue.empty());
+    void ValidateAudioHalCapCriterion(const AudioHalCapCriterionV2& criterionV2) {
+        switch (criterionV2.getTag()) {
+            case AudioHalCapCriterionV2::availableInputDevices: {
+                auto criterion = criterionV2.get<AudioHalCapCriterionV2::availableInputDevices>();
+                EXPECT_FALSE(criterion.values.empty());
+                EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+                break;
+            }
+            case AudioHalCapCriterionV2::availableOutputDevices: {
+                auto criterion = criterionV2.get<AudioHalCapCriterionV2::availableOutputDevices>();
+                EXPECT_FALSE(criterion.values.empty());
+                EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+                break;
+            }
+            case AudioHalCapCriterionV2::availableInputDevicesAddresses: {
+                auto criterion =
+                        criterionV2.get<AudioHalCapCriterionV2::availableInputDevicesAddresses>();
+                EXPECT_FALSE(criterion.values.empty());
+                EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+                break;
+            }
+            case AudioHalCapCriterionV2::availableOutputDevicesAddresses: {
+                auto criterion =
+                        criterionV2.get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>();
+                EXPECT_FALSE(criterion.values.empty());
+                EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+                break;
+            }
+            case AudioHalCapCriterionV2::telephonyMode: {
+                auto criterion = criterionV2.get<AudioHalCapCriterionV2::telephonyMode>();
+                EXPECT_FALSE(criterion.values.empty());
+                EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::EXCLUSIVE);
+                break;
+            }
+            case AudioHalCapCriterionV2::forceConfigForUse: {
+                auto criterion = criterionV2.get<AudioHalCapCriterionV2::forceConfigForUse>();
+                EXPECT_FALSE(criterion.values.empty());
+                EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::EXCLUSIVE);
+                break;
+            }
+            default:
+                ADD_FAILURE() << "Invalid criterion tag " << toString(criterionV2.getTag());
         }
     }
 
     /**
-     * Verify values only contain alphanumeric characters.
+     * Verify the rule involve the right matching logic according to the criterion logic.
+     * @param matchingRule logic followed by the rule
+     * @param logicalDisjunction logic exposed by the criterion
      */
-    void ValidateAudioHalCapCriterionType(const AudioHalCapCriterionType& criterionType) {
-        auto isNotAlnum = [](const char& c) { return !isalnum(c); };
-        for (const std::string& value : criterionType.values) {
-            EXPECT_EQ(find_if(value.begin(), value.end(), isNotAlnum), value.end());
+    void ValidateAudioHalCapRuleMatchingRule(
+            const AudioHalCapRule::MatchingRule matchingRule,
+            const AudioHalCapCriterionV2::LogicalDisjunction logicalDisjunction) {
+        if (logicalDisjunction == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE) {
+            EXPECT_TRUE(matchingRule == AudioHalCapRule::MatchingRule::EXCLUDES ||
+                        matchingRule == AudioHalCapRule::MatchingRule::INCLUDES);
+        } else if (logicalDisjunction == AudioHalCapCriterionV2::LogicalDisjunction::EXCLUSIVE) {
+            EXPECT_TRUE(matchingRule == AudioHalCapRule::MatchingRule::IS ||
+                        matchingRule == AudioHalCapRule::MatchingRule::IS_NOT);
+        } else {
+            ADD_FAILURE() << "Invalid criterion Logical rule";
         }
     }
 
     /**
-     * Verify each criterionType has a unique name.
-     * Verify each criterion has a unique name.
-     * Verify each criterion maps to a criterionType.
-     * Verify each criterionType is used in a criterion.
-     * Validate contained types.
+     * Verify that the value and the matching rule are supported by the given criterion
+     */
+    template <typename CriterionV2, typename Value>
+    void validateAudioHalCapRule(CriterionV2 criterionV2, Value value,
+                                 const AudioHalCapRule::MatchingRule matchingRule) {
+        ValidateAudioHalCapRuleMatchingRule(matchingRule, criterionV2.logic);
+        EXPECT_FALSE(criterionV2.values.empty());
+        auto values = criterionV2.values;
+        auto valueIt = find_if(values.begin(), values.end(),
+                               [&](const auto& typedValue) { return typedValue == value; });
+        EXPECT_NE(valueIt, values.end());
+    }
+
+    /**
+     * Verify rule involves a supported criterion.
+     * Verify rule involves supported logic keyword according to logic rule exposed by the
+     * criterion.
+     * Verify rule involves a value supported by the associated criterion.
+     */
+    void ValidateAudioHalConfigurationRule(
+            const AudioHalCapRule& rule,
+            const std::vector<std::optional<AudioHalCapCriterionV2>>& criteria) {
+        const auto& compoundRule = rule.compoundRule;
+        if (rule.nestedRules.empty() && rule.criterionRules.empty()) {
+            EXPECT_EQ(compoundRule, AudioHalCapRule::CompoundRule::ALL);
+        }
+        EXPECT_TRUE(compoundRule == AudioHalCapRule::CompoundRule::ANY ||
+                    compoundRule == AudioHalCapRule::CompoundRule::ALL);
+        for (const auto& nestedRule : rule.nestedRules) {
+            ValidateAudioHalConfigurationRule(nestedRule, criteria);
+        }
+        for (const auto& criterionRule : rule.criterionRules) {
+            auto selectionCriterion = criterionRule.criterionAndValue;
+            auto criterionValue = criterionRule.criterionAndValue;
+            auto matchesWhen = criterionRule.matchingRule;
+            auto criteriaIt = find_if(criteria.begin(), criteria.end(), [&](const auto& criterion) {
+                return criterion.has_value() &&
+                       criterion.value().getTag() == selectionCriterion.getTag();
+            });
+            EXPECT_NE(criteriaIt, criteria.end())
+                    << " Invalid rule criterion " << toString(selectionCriterion.getTag());
+            AudioHalCapCriterionV2 matchingCriterion = (*criteriaIt).value();
+            switch (selectionCriterion.getTag()) {
+                case AudioHalCapCriterionV2::availableInputDevices: {
+                    const auto& values =
+                            criterionValue.get<AudioHalCapCriterionV2::availableInputDevices>()
+                                    .values;
+                    ASSERT_FALSE(values.empty());
+                    validateAudioHalCapRule(
+                            matchingCriterion.get<AudioHalCapCriterionV2::availableInputDevices>(),
+                            values[0], matchesWhen);
+                    break;
+                }
+                case AudioHalCapCriterionV2::availableOutputDevices: {
+                    const auto& values =
+                            criterionValue.get<AudioHalCapCriterionV2::availableOutputDevices>()
+                                    .values;
+                    ASSERT_FALSE(values.empty());
+                    validateAudioHalCapRule(
+                            matchingCriterion.get<AudioHalCapCriterionV2::availableOutputDevices>(),
+                            values[0], matchesWhen);
+                    break;
+                }
+                case AudioHalCapCriterionV2::availableInputDevicesAddresses: {
+                    const auto& values =
+                            criterionValue
+                                    .get<AudioHalCapCriterionV2::availableInputDevicesAddresses>()
+                                    .values;
+                    ASSERT_FALSE(values.empty());
+                    validateAudioHalCapRule(
+                            matchingCriterion
+                                    .get<AudioHalCapCriterionV2::availableInputDevicesAddresses>(),
+                            values[0], matchesWhen);
+                    break;
+                }
+                case AudioHalCapCriterionV2::availableOutputDevicesAddresses: {
+                    const auto& values =
+                            criterionValue
+                                    .get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>()
+                                    .values;
+                    ASSERT_FALSE(values.empty());
+                    validateAudioHalCapRule(
+                            matchingCriterion
+                                    .get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>(),
+                            values[0], matchesWhen);
+                    break;
+                }
+                case AudioHalCapCriterionV2::telephonyMode: {
+                    const auto& values =
+                            criterionValue.get<AudioHalCapCriterionV2::telephonyMode>().values;
+                    ASSERT_FALSE(values.empty());
+                    validateAudioHalCapRule(
+                            matchingCriterion.get<AudioHalCapCriterionV2::telephonyMode>(),
+                            values[0], matchesWhen);
+                    break;
+                }
+                case AudioHalCapCriterionV2::forceConfigForUse: {
+                    const auto& values =
+                            criterionValue.get<AudioHalCapCriterionV2::forceConfigForUse>().values;
+                    ASSERT_FALSE(values.empty());
+                    validateAudioHalCapRule(
+                            matchingCriterion.get<AudioHalCapCriterionV2::forceConfigForUse>(),
+                            values[0], matchesWhen);
+                    break;
+                }
+                default:
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Get the number of occurrence of a given parameter within a given vector of parameter.
+     * It just take into account the parameter, not its associated value.
+     * @param parameter to consider
+     * @param domainParameters to check against
+     * @return matching occurrence of the parameter within the provided vector.
+     */
+    size_t countsParameter(const AudioHalCapParameter& parameter,
+                           const std::vector<AudioHalCapParameter>& domainParameters) {
+        size_t count = 0;
+        for (const auto& domainParameter : domainParameters) {
+            if (domainParameter.getTag() != parameter.getTag()) {
+                continue;
+            }
+            switch (domainParameter.getTag()) {
+                case AudioHalCapParameter::selectedStrategyDevice: {
+                    auto typedDomainParam =
+                            domainParameter.get<AudioHalCapParameter::selectedStrategyDevice>();
+                    auto typedParam = parameter.get<AudioHalCapParameter::selectedStrategyDevice>();
+                    if (typedDomainParam.id == typedParam.id &&
+                        typedDomainParam.device == typedParam.device) {
+                        count += 1;
+                    }
+                    break;
+                }
+                case AudioHalCapParameter::strategyDeviceAddress: {
+                    auto typedDomainParam =
+                            domainParameter.get<AudioHalCapParameter::strategyDeviceAddress>();
+                    auto typedParam = parameter.get<AudioHalCapParameter::strategyDeviceAddress>();
+                    if (typedDomainParam.id == typedParam.id) {
+                        count += 1;
+                    }
+                    break;
+                }
+                case AudioHalCapParameter::selectedInputSourceDevice: {
+                    auto typedDomainParam =
+                            domainParameter.get<AudioHalCapParameter::selectedInputSourceDevice>();
+                    auto typedParam =
+                            parameter.get<AudioHalCapParameter::selectedInputSourceDevice>();
+                    if (typedDomainParam.inputSource == typedParam.inputSource &&
+                        typedDomainParam.device == typedParam.device) {
+                        count += 1;
+                    }
+                    break;
+                }
+                case AudioHalCapParameter::streamVolumeProfile: {
+                    auto typedDomainParam =
+                            domainParameter.get<AudioHalCapParameter::streamVolumeProfile>();
+                    auto typedParam = parameter.get<AudioHalCapParameter::streamVolumeProfile>();
+                    if (typedDomainParam.stream == typedParam.stream) {
+                        count += 1;
+                    }
+                    break;
+                }
+                default:
+                    break;
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Verify each configuration has unique name within a domain
+     * Verify no duplicate parameter within a domain.
+     * Verify that each configuration has no duplicated parameter.
+     * Verify that each configuration has an associated value for all parameter within a domain.
+     */
+    void ValidateAudioHalCapDomain(
+            const AudioHalCapDomain& domain,
+            const std::vector<std::optional<AudioHalCapCriterionV2>>& criteria) {
+        std::unordered_set<std::string> configurationNames;
+        for (const AudioHalCapConfiguration& configuration : domain.configurations) {
+            EXPECT_TRUE(configurationNames.insert(configuration.name).second);
+            ValidateAudioHalConfigurationRule(configuration.rule, criteria);
+        }
+        auto domainParameters = domain.configurations[0].parameterSettings;
+        for (const auto& settingParameter : domainParameters) {
+            EXPECT_EQ(1ul, countsParameter(settingParameter, domainParameters))
+                    << "Duplicated parameter within domain " << domain.name << " configuration "
+                    << domain.configurations[0].name << " for parameter "
+                    << settingParameter.toString();
+        }
+        for (const auto& configuration : domain.configurations) {
+            auto configurationParameters = configuration.parameterSettings;
+            for (const auto& configurationParameter : configurationParameters) {
+                EXPECT_EQ(1ul, countsParameter(configurationParameter, configurationParameters))
+                        << "Duplicated parameter within domain " << domain.name << " configuration "
+                        << configuration.name << " for parameter "
+                        << configurationParameter.toString();
+            }
+            EXPECT_EQ(domainParameters.size(), configurationParameters.size());
+            for (const auto& settingParameter : configuration.parameterSettings) {
+                EXPECT_EQ(1ul, countsParameter(settingParameter, domainParameters))
+                        << "Confiugration " << configuration.name << " within domain "
+                        << domain.name << " exposes invalid parameter "
+                        << settingParameter.toString();
+                ;
+            }
+        }
+    }
+
+    /**
+     * Verify each domain has a unique name.
+     * Verify that a given parameter does not appear in more than one domain.
+     */
+    void ValidateAudioHalCapDomains(
+            const std::vector<std::optional<AudioHalCapDomain>>& domains,
+            const std::vector<std::optional<AudioHalCapCriterionV2>>& criteria) {
+        std::unordered_map<std::string, AudioHalCapDomain> domainMap;
+        std::vector<AudioHalCapParameter> allDomainParameters;
+        for (const auto& domain : domains) {
+            EXPECT_TRUE(domain.has_value());
+            EXPECT_FALSE(domain.value().configurations.empty());
+            auto domainParameters = domain.value().configurations[0].parameterSettings;
+            for (const auto& domainParameter : domainParameters) {
+                EXPECT_EQ(0ul, countsParameter(domainParameter, allDomainParameters))
+                        << "Duplicated parameter in domain " << domain.value().name
+                        << " for parameter " << domainParameter.toString();
+                allDomainParameters.push_back(domainParameter);
+            }
+            EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapDomain(domain.value(), criteria));
+            EXPECT_TRUE(domainMap.insert({domain.value().name, domain.value()}).second);
+        }
+    }
+
+    /**
+     * Verify unique criterion is provided for a given Tag, except for ForceUse
+     * Verify unique forceUse criterion are provided for usage
+     * Verify each criterion is validating.
+     * Verify domains.
      */
     void ValidateCapSpecificConfig(const AudioHalEngineConfig::CapSpecificConfig& capCfg) {
-        EXPECT_FALSE(capCfg.criteria.empty());
-        EXPECT_FALSE(capCfg.criterionTypes.empty());
-        std::unordered_map<std::string, AudioHalCapCriterionType> criterionTypeMap;
-        for (const AudioHalCapCriterionType& criterionType : capCfg.criterionTypes) {
-            EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapCriterionType(criterionType));
-            EXPECT_TRUE(criterionTypeMap.insert({criterionType.name, criterionType}).second);
+        EXPECT_TRUE(capCfg.criteriaV2.has_value());
+        std::unordered_set<AudioHalCapCriterionV2::Tag> criterionTagSet;
+        std::unordered_set<AudioPolicyForceUse::Tag> forceUseCriterionUseSet;
+        for (const auto& criterion : capCfg.criteriaV2.value()) {
+            EXPECT_TRUE(criterion.has_value());
+            if (criterion.value().getTag() != AudioHalCapCriterionV2::forceConfigForUse) {
+                EXPECT_TRUE(criterionTagSet.insert(criterion.value().getTag()).second);
+            } else {
+                auto forceUseCriterion =
+                        criterion.value().get<AudioHalCapCriterionV2::forceConfigForUse>();
+                ASSERT_FALSE(forceUseCriterion.values.empty());
+                EXPECT_TRUE(forceUseCriterionUseSet.insert(forceUseCriterion.values[0].getTag())
+                                    .second);
+            }
+            EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapCriterion(criterion.value()));
         }
-        std::unordered_set<std::string> criterionNameSet;
-        for (const AudioHalCapCriterion& criterion : capCfg.criteria) {
-            EXPECT_TRUE(criterionNameSet.insert(criterion.name).second);
-            EXPECT_EQ(criterionTypeMap.count(criterion.criterionTypeName), 1UL);
-            EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapCriterion(
-                    criterion, criterionTypeMap.at(criterion.criterionTypeName)));
-        }
-        EXPECT_EQ(criterionTypeMap.size(), criterionNameSet.size());
+        ValidateAudioHalCapDomains(capCfg.domains.value(), capCfg.criteriaV2.value());
     }
 
     /**
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 633fe52..750e54d 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -80,6 +80,7 @@
 using aidl::android::hardware::audio::core::VendorParameter;
 using aidl::android::hardware::audio::core::sounddose::ISoundDose;
 using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using aidl::android::media::audio::common::AudioChannelLayout;
 using aidl::android::media::audio::common::AudioContentType;
 using aidl::android::media::audio::common::AudioDevice;
 using aidl::android::media::audio::common::AudioDeviceAddress;
@@ -87,6 +88,7 @@
 using aidl::android::media::audio::common::AudioDeviceType;
 using aidl::android::media::audio::common::AudioDualMonoMode;
 using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioGainConfig;
 using aidl::android::media::audio::common::AudioInputFlags;
 using aidl::android::media::audio::common::AudioIoFlags;
 using aidl::android::media::audio::common::AudioLatencyMode;
@@ -115,6 +117,10 @@
 using ndk::enum_range;
 using ndk::ScopedAStatus;
 
+static constexpr int32_t kAidlVersion1 = 1;
+static constexpr int32_t kAidlVersion2 = 2;
+static constexpr int32_t kAidlVersion3 = 3;
+
 template <typename T>
 std::set<int32_t> extractIds(const std::vector<T>& v) {
     std::set<int32_t> ids;
@@ -370,7 +376,8 @@
 template <typename PropType, class Instance, typename Getter, typename Setter>
 void TestAccessors(Instance* inst, Getter getter, Setter setter,
                    const std::vector<PropType>& validValues,
-                   const std::vector<PropType>& invalidValues, bool* isSupported) {
+                   const std::vector<PropType>& invalidValues, bool* isSupported,
+                   const std::vector<PropType>* ambivalentValues = nullptr) {
     PropType initialValue{};
     ScopedAStatus status = (inst->*getter)(&initialValue);
     if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
@@ -389,6 +396,15 @@
         EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, (inst->*setter)(v))
                 << "for an invalid value: " << ::testing::PrintToString(v);
     }
+    if (ambivalentValues != nullptr) {
+        for (const auto v : *ambivalentValues) {
+            const auto status = (inst->*setter)(v);
+            if (!status.isOk()) {
+                EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, status)
+                        << "for an ambivalent value: " << ::testing::PrintToString(v);
+            }
+        }
+    }
     EXPECT_IS_OK((inst->*setter)(initialValue)) << "Failed to restore the initial value";
 }
 
@@ -478,6 +494,7 @@
         if (setUpDebug) {
             ASSERT_NO_FATAL_FAILURE(SetUpDebug());
         }
+        ASSERT_TRUE(module->getInterfaceVersion(&aidlVersion).isOk());
     }
 
     void RestartService() {
@@ -490,6 +507,7 @@
         if (setUpDebug) {
             ASSERT_NO_FATAL_FAILURE(SetUpDebug());
         }
+        ASSERT_TRUE(module->getInterfaceVersion(&aidlVersion).isOk());
     }
 
     void SetUpDebug() {
@@ -577,6 +595,7 @@
     std::unique_ptr<WithDebugFlags> debug;
     std::vector<AudioPort> initialPorts;
     std::vector<AudioRoute> initialRoutes;
+    int32_t aidlVersion = -1;
 };
 
 class WithDevicePortConnectedState {
@@ -919,6 +938,8 @@
         LOG(DEBUG) << __func__;
         return "";
     }
+    const std::vector<int8_t>& getData() const { return mData; }
+    void fillData(int8_t filler) { std::fill(mData.begin(), mData.end(), filler); }
     std::optional<StreamDescriptor::Command> maybeGetNextCommand(int* actualSize = nullptr) {
         TransitionTrigger trigger = mDriver->getNextTrigger(mData.size(), actualSize);
         if (StreamEventReceiver::Event* expEvent =
@@ -988,6 +1009,8 @@
     StreamReaderLogic(const StreamContext& context, StreamLogicDriver* driver,
                       StreamEventReceiver* eventReceiver)
         : StreamCommonLogic(context, driver, eventReceiver) {}
+    // Should only be called after the worker has joined.
+    const std::vector<int8_t>& getData() const { return StreamCommonLogic::getData(); }
 
   protected:
     Status cycle() override {
@@ -1053,6 +1076,7 @@
         if (const size_t readCount =
                     !isMmapped() ? getDataMQ()->availableToRead() : reply.fmqByteCount;
             readCount > 0) {
+            fillData(-1);
             if (isMmapped() ? readDataFromMmap(readCount) : readDataFromMQ(readCount)) {
                 goto checkAcceptedReply;
             }
@@ -1074,6 +1098,8 @@
     StreamWriterLogic(const StreamContext& context, StreamLogicDriver* driver,
                       StreamEventReceiver* eventReceiver)
         : StreamCommonLogic(context, driver, eventReceiver) {}
+    // Should only be called after the worker has joined.
+    const std::vector<int8_t>& getData() const { return StreamCommonLogic::getData(); }
 
   protected:
     Status cycle() override {
@@ -1090,6 +1116,14 @@
             return Status::ABORT;
         }
         if (actualSize != 0) {
+            if (command.getTag() == StreamDescriptor::Command::burst) {
+                fillData(mBurstIteration);
+                if (mBurstIteration < std::numeric_limits<int8_t>::max()) {
+                    mBurstIteration++;
+                } else {
+                    mBurstIteration = 0;
+                }
+            }
             if (isMmapped() ? !writeDataToMmap() : !writeDataToMQ()) {
                 return Status::ABORT;
             }
@@ -1148,6 +1182,9 @@
         LOG(ERROR) << __func__ << ": unacceptable reply: " << reply.toString();
         return Status::ABORT;
     }
+
+  private:
+    int8_t mBurstIteration = 1;
 };
 using StreamWriter = StreamWorker<StreamWriterLogic>;
 
@@ -1509,7 +1546,7 @@
     const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
     for (const auto& port : ports) {
         if (port.ext.getTag() != AudioPortExt::Tag::device) continue;
-        const auto& devicePort = port.ext.get<AudioPortExt::Tag::device>();
+        const AudioPortDeviceExt& devicePort = port.ext.get<AudioPortExt::Tag::device>();
         EXPECT_NE(AudioDeviceType::NONE, devicePort.device.type.type);
         EXPECT_NE(AudioDeviceType::IN_DEFAULT, devicePort.device.type.type);
         EXPECT_NE(AudioDeviceType::OUT_DEFAULT, devicePort.device.type.type);
@@ -1544,6 +1581,15 @@
                 FAIL() << "Invalid AudioIoFlags Tag: " << toString(port.flags.getTag());
             }
         }
+        // Speaker layout can be null or layoutMask variant.
+        if (devicePort.speakerLayout.has_value()) {
+            // Should only be set for output ports.
+            EXPECT_EQ(AudioIoFlags::Tag::output, port.flags.getTag());
+            const auto speakerLayoutTag = devicePort.speakerLayout.value().getTag();
+            EXPECT_EQ(AudioChannelLayout::Tag::layoutMask, speakerLayoutTag)
+                    << "If set, speaker layout must be layoutMask.  Received: "
+                    << toString(speakerLayoutTag);
+        }
     }
 }
 
@@ -1821,6 +1867,47 @@
     }
 }
 
+TEST_P(AudioCoreModule, SetAudioPortConfigInvalidPortAudioGain) {
+    ASSERT_GE(aidlVersion, kAidlVersion1);
+    if (aidlVersion < kAidlVersion3) {
+        GTEST_SKIP() << "Skip for audio HAL version lower than " << kAidlVersion3;
+    }
+    std::vector<AudioPort> ports;
+    ASSERT_IS_OK(module->getAudioPorts(&ports));
+    bool atLeastOnePortWithNonemptyGain = false;
+    for (const auto port : ports) {
+        AudioPortConfig portConfig;
+        portConfig.portId = port.id;
+        if (port.gains.empty()) {
+            continue;
+        }
+        atLeastOnePortWithNonemptyGain = true;
+        int index = 0;
+        ASSERT_NE(0, port.gains[index].stepValue) << "Invalid audio port config gain step 0";
+        portConfig.gain->index = index;
+        AudioGainConfig invalidGainConfig;
+
+        int invalidGain = port.gains[index].maxValue + port.gains[index].stepValue;
+        invalidGainConfig.values.push_back(invalidGain);
+        portConfig.gain.emplace(invalidGainConfig);
+        bool applied = true;
+        AudioPortConfig suggestedConfig;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+                      module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
+                << "invalid port gain " << invalidGain << " lower than min gain";
+
+        invalidGain = port.gains[index].minValue - port.gains[index].stepValue;
+        invalidGainConfig.values[0] = invalidGain;
+        portConfig.gain.emplace(invalidGainConfig);
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+                      module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
+                << "invalid port gain " << invalidGain << "higher than max gain";
+    }
+    if (!atLeastOnePortWithNonemptyGain) {
+        GTEST_SKIP() << "No audio port contains non-empty gain configuration";
+    }
+}
+
 TEST_P(AudioCoreModule, TryConnectMissingDevice) {
     // Limit checks to connection types that are known to be detectable by HAL implementations.
     static const std::set<std::string> kCheckedConnectionTypes{
@@ -2790,10 +2877,12 @@
         ASSERT_NO_FATAL_FAILURE(mStream->SetUpStream(module, getMinimumStreamBufferSizeFrames()));
     }
 
-    void SetUpStreamForDevicePort(IModule* module, ModuleConfig* moduleConfig,
-                                  const AudioPort& devicePort, bool connectedOnly = false) {
-        ASSERT_NO_FATAL_FAILURE(
-                SetUpPortConfigForDevicePort(module, moduleConfig, devicePort, connectedOnly));
+    void SetUpStreamForDevicePort(
+            IModule* module, ModuleConfig* moduleConfig, const AudioPort& devicePort,
+            bool connectedOnly = false,
+            const std::optional<AudioDeviceAddress>& connectionAddress = std::nullopt) {
+        ASSERT_NO_FATAL_FAILURE(SetUpPortConfigForDevicePort(module, moduleConfig, devicePort,
+                                                             connectedOnly, connectionAddress));
         if (!mSkipTestReason.empty()) return;
         ASSERT_NO_FATAL_FAILURE(SetUpStream(module));
     }
@@ -2829,6 +2918,23 @@
         if (!mSkipTestReason.empty()) return;
         ASSERT_NO_FATAL_FAILURE(SetUpStream(module));
     }
+    void SetUpStreamForNewMixPortConfig(IModule* module, ModuleConfig*,
+                                        const AudioPortConfig& existingMixPortConfig,
+                                        const AudioPortConfig& existingDevicePortConfig) {
+        auto mixPortConfig = existingMixPortConfig;
+        mixPortConfig.id = 0;
+        mMixPortConfig = std::make_unique<WithAudioPortConfig>(mixPortConfig);
+        ASSERT_NO_FATAL_FAILURE(mMixPortConfig->SetUp(module));
+        mDevicePortConfig = std::make_unique<WithAudioPortConfig>(existingDevicePortConfig);
+        ASSERT_NO_FATAL_FAILURE(mDevicePortConfig->SetUp(module));
+        mDevice = existingDevicePortConfig.ext.get<AudioPortExt::device>().device;
+        mPatch = std::make_unique<WithAudioPatch>(mIsInput, mMixPortConfig->get(),
+                                                  mDevicePortConfig->get());
+        ASSERT_NO_FATAL_FAILURE(mPatch->SetUp(module));
+        mStream = std::make_unique<WithStream<Stream>>(mMixPortConfig->get());
+        ASSERT_NO_FATAL_FAILURE(mStream->SetUpPortConfig(module));
+        ASSERT_NO_FATAL_FAILURE(SetUpStream(module));
+    }
     void SetUpPatchForMixPortConfig(IModule* module, ModuleConfig* moduleConfig,
                                     const AudioPortConfig& mixPortConfig) {
         constexpr bool connectedOnly = true;
@@ -2860,6 +2966,7 @@
     }
 
     const AudioDevice& getDevice() const { return mDevice; }
+    const AudioPortConfig& getDevicePortConfig() const { return mDevicePortConfig->get(); }
     int32_t getMinimumStreamBufferSizeFrames() const {
         return mPatch->getMinimumStreamBufferSizeFrames();
     }
@@ -2875,7 +2982,8 @@
   private:
     void SetUpDevicePort(IModule* module, ModuleConfig* moduleConfig,
                          const std::set<int32_t>& devicePortIds, bool connectedOnly,
-                         std::optional<AudioPort>* connectedDevicePort) {
+                         std::optional<AudioPort>* connectedDevicePort,
+                         const std::optional<AudioDeviceAddress>& connectionAddress) {
         const auto attachedDevicePorts = moduleConfig->getAttachedDevicePorts();
         if (auto it = findAny<AudioPort>(attachedDevicePorts, devicePortIds);
             it != attachedDevicePorts.end()) {
@@ -2892,7 +3000,12 @@
             const auto externalDevicePorts = moduleConfig->getExternalDevicePorts();
             if (auto it = findAny<AudioPort>(externalDevicePorts, devicePortIds);
                 it != externalDevicePorts.end()) {
-                AudioPort portWithData = GenerateUniqueDeviceAddress(*it);
+                AudioPort portWithData = *it;
+                if (connectionAddress.has_value()) {
+                    portWithData.ext.get<AudioPortExt::Tag::device>().device.address =
+                            *connectionAddress;
+                }
+                portWithData = GenerateUniqueDeviceAddress(portWithData);
                 mPortConnected = std::make_unique<WithDevicePortConnectedState>(portWithData);
                 ASSERT_NO_FATAL_FAILURE(mPortConnected->SetUp(module, moduleConfig));
                 *connectedDevicePort = mPortConnected->get();
@@ -2911,9 +3024,9 @@
             LOG(DEBUG) << __func__ << ": " << mSkipTestReason;
             return;
         };
-        ASSERT_NO_FATAL_FAILURE(SetUpDevicePort(module, moduleConfig,
-                                                extractIds<AudioPort>(devicePorts), connectedOnly,
-                                                connectedDevicePort));
+        ASSERT_NO_FATAL_FAILURE(SetUpDevicePort(
+                module, moduleConfig, extractIds<AudioPort>(devicePorts), connectedOnly,
+                connectedDevicePort, std::nullopt /*connectionAddress*/));
         if (!connectedDevicePort->has_value()) {
             mSkipTestReason = std::string("Unable to find a device port pair for mix port id ")
                                       .append(std::to_string(mixPort.id));
@@ -2921,11 +3034,14 @@
             return;
         }
     }
-    void SetUpPortConfigForDevicePort(IModule* module, ModuleConfig* moduleConfig,
-                                      const AudioPort& devicePort, bool connectedOnly) {
+    void SetUpPortConfigForDevicePort(
+            IModule* module, ModuleConfig* moduleConfig, const AudioPort& devicePort,
+            bool connectedOnly,
+            const std::optional<AudioDeviceAddress>& connectionAddress = std::nullopt) {
         std::optional<AudioPort> connectedDevicePort;
         ASSERT_NO_FATAL_FAILURE(SetUpDevicePort(module, moduleConfig, {devicePort.id},
-                                                connectedOnly, &connectedDevicePort));
+                                                connectedOnly, &connectedDevicePort,
+                                                connectionAddress));
         if (!connectedDevicePort.has_value()) {
             mSkipTestReason = std::string("Device port id ")
                                       .append(std::to_string(devicePort.id))
@@ -2975,15 +3091,15 @@
 
     // The five methods below is intended to be called after the worker
     // thread has joined, thus no extra synchronization is needed.
-    bool hasObservablePositionIncrease() const { return mObservablePositionIncrease; }
-    bool hasObservableRetrogradePosition() const { return mRetrogradeObservablePosition; }
+    bool hasObservablePositionIncrease() const { return mObservable.hasPositionIncrease; }
+    bool hasObservableRetrogradePosition() const { return mObservable.hasRetrogradePosition; }
     bool hasHardwarePositionIncrease() const {
         // For non-MMap, always return true to pass the validation.
-        return mIsMmap ? mHardwarePositionIncrease : true;
+        return mIsMmap ? mHardware.hasPositionIncrease : true;
     }
     bool hasHardwareRetrogradePosition() const {
         // For non-MMap, always return false to pass the validation.
-        return mIsMmap ? mRetrogradeHardwarePosition : false;
+        return mIsMmap ? mHardware.hasRetrogradePosition : false;
     }
     std::string getUnexpectedStateTransition() const { return mUnexpectedTransition; }
 
@@ -3011,25 +3127,9 @@
     }
     bool interceptRawReply(const StreamDescriptor::Reply&) override { return false; }
     bool processValidReply(const StreamDescriptor::Reply& reply) override {
-        if (reply.observable.frames != StreamDescriptor::Position::UNKNOWN) {
-            if (mPreviousObservableFrames.has_value()) {
-                if (reply.observable.frames > mPreviousObservableFrames.value()) {
-                    mObservablePositionIncrease = true;
-                } else if (reply.observable.frames < mPreviousObservableFrames.value()) {
-                    mRetrogradeObservablePosition = true;
-                }
-            }
-            mPreviousObservableFrames = reply.observable.frames;
-        }
+        mObservable.update(reply.observable.frames);
         if (mIsMmap) {
-            if (mPreviousHardwareFrames.has_value()) {
-                if (reply.hardware.frames > mPreviousHardwareFrames.value()) {
-                    mHardwarePositionIncrease = true;
-                } else if (reply.hardware.frames < mPreviousHardwareFrames.value()) {
-                    mRetrogradeHardwarePosition = true;
-                }
-            }
-            mPreviousHardwareFrames = reply.hardware.frames;
+            mHardware.update(reply.hardware.frames);
         }
 
         auto expected = mCommands->getExpectedStates();
@@ -3054,21 +3154,36 @@
     }
 
   protected:
+    struct FramesCounter {
+        std::optional<int64_t> previous;
+        bool hasPositionIncrease = false;
+        bool hasRetrogradePosition = false;
+
+        void update(int64_t position) {
+            if (position == StreamDescriptor::Position::UNKNOWN) return;
+            if (previous.has_value()) {
+                if (position > previous.value()) {
+                    hasPositionIncrease = true;
+                } else if (position < previous.value()) {
+                    hasRetrogradePosition = true;
+                }
+            }
+            previous = position;
+        }
+    };
+
     std::shared_ptr<StateSequence> mCommands;
     const size_t mFrameSizeBytes;
     const bool mIsMmap;
     std::optional<StreamDescriptor::State> mPreviousState;
-    std::optional<int64_t> mPreviousObservableFrames;
-    bool mObservablePositionIncrease = false;
-    bool mRetrogradeObservablePosition = false;
-    std::optional<int64_t> mPreviousHardwareFrames;
-    bool mHardwarePositionIncrease = false;
-    bool mRetrogradeHardwarePosition = false;
+    FramesCounter mObservable;
+    FramesCounter mHardware;
     std::string mUnexpectedTransition;
 };
 
 // Defined later together with state transition sequences.
-std::shared_ptr<StateSequence> makeBurstCommands(bool isSync);
+std::shared_ptr<StateSequence> makeBurstCommands(bool isSync, size_t burstCount = 10,
+                                                 bool standbyInputWhenDone = false);
 
 // Certain types of ports can not be used without special preconditions.
 static bool skipStreamIoTestForMixPortConfig(const AudioPortConfig& portConfig) {
@@ -3093,10 +3208,11 @@
   public:
     explicit StreamFixtureWithWorker(bool isSync) : mIsSync(isSync) {}
 
-    void SetUp(IModule* module, ModuleConfig* moduleConfig, const AudioPort& devicePort) {
+    void SetUp(IModule* module, ModuleConfig* moduleConfig, const AudioPort& devicePort,
+               const std::optional<AudioDeviceAddress>& connectionAddress = std::nullopt) {
         mStream = std::make_unique<StreamFixture<Stream>>();
-        ASSERT_NO_FATAL_FAILURE(
-                mStream->SetUpStreamForDevicePort(module, moduleConfig, devicePort));
+        ASSERT_NO_FATAL_FAILURE(mStream->SetUpStreamForDevicePort(
+                module, moduleConfig, devicePort, false /*connectedOnly*/, connectionAddress));
         MaybeSetSkipTestReason();
     }
 
@@ -3108,26 +3224,42 @@
         MaybeSetSkipTestReason();
     }
 
-    void SendBurstCommands(bool validatePosition = true) {
-        ASSERT_NO_FATAL_FAILURE(StartWorkerToSendBurstCommands());
+    void SetUp(IModule* module, ModuleConfig* moduleConfig,
+               const AudioPortConfig& existingMixPortConfig,
+               const AudioPortConfig& existingDevicePortConfig) {
+        mStream = std::make_unique<StreamFixture<Stream>>();
+        ASSERT_NO_FATAL_FAILURE(mStream->SetUpStreamForNewMixPortConfig(
+                module, moduleConfig, existingMixPortConfig, existingDevicePortConfig));
+        MaybeSetSkipTestReason();
+    }
+
+    void SendBurstCommands(bool validatePosition = true, size_t burstCount = 10,
+                           bool standbyInputWhenDone = false) {
+        ASSERT_NO_FATAL_FAILURE(StartWorkerToSendBurstCommands(burstCount, standbyInputWhenDone));
         ASSERT_NO_FATAL_FAILURE(JoinWorkerAfterBurstCommands(validatePosition));
     }
 
-    void StartWorkerToSendBurstCommands() {
+    void StartWorkerToSendBurstCommands(size_t burstCount = 10, bool standbyInputWhenDone = false) {
+        if (!IOTraits<Stream>::is_input) {
+            ASSERT_FALSE(standbyInputWhenDone) << "Only supported for input";
+        }
         const StreamContext* context = mStream->getStreamContext();
         mWorkerDriver = std::make_unique<StreamLogicDefaultDriver>(
-                makeBurstCommands(mIsSync), context->getFrameSizeBytes(), context->isMmapped());
+                makeBurstCommands(mIsSync, burstCount, standbyInputWhenDone),
+                context->getFrameSizeBytes(), context->isMmapped());
         mWorker = std::make_unique<typename IOTraits<Stream>::Worker>(
                 *context, mWorkerDriver.get(), mStream->getStreamEventReceiver());
         LOG(DEBUG) << __func__ << ": starting " << IOTraits<Stream>::directionStr << " worker...";
         ASSERT_TRUE(mWorker->start());
     }
 
-    void JoinWorkerAfterBurstCommands(bool validatePosition = true) {
-        // Must call 'prepareToClose' before attempting to join because the stream may be stuck.
-        std::shared_ptr<IStreamCommon> common;
-        ASSERT_IS_OK(mStream->getStream()->getStreamCommon(&common));
-        ASSERT_IS_OK(common->prepareToClose());
+    void JoinWorkerAfterBurstCommands(bool validatePosition = true,
+                                      bool callPrepareToClose = true) {
+        if (callPrepareToClose) {
+            std::shared_ptr<IStreamCommon> common;
+            ASSERT_IS_OK(mStream->getStream()->getStreamCommon(&common));
+            ASSERT_IS_OK(common->prepareToClose());
+        }
         LOG(DEBUG) << __func__ << ": joining " << IOTraits<Stream>::directionStr << " worker...";
         mWorker->join();
         EXPECT_FALSE(mWorker->hasError()) << mWorker->getError();
@@ -3138,6 +3270,7 @@
             EXPECT_FALSE(mWorkerDriver->hasObservableRetrogradePosition());
             EXPECT_FALSE(mWorkerDriver->hasHardwareRetrogradePosition());
         }
+        mLastData = mWorker->getData();
         mWorker.reset();
         mWorkerDriver.reset();
     }
@@ -3145,6 +3278,9 @@
     void TeardownPatch() { mStream->TeardownPatch(); }
 
     const AudioDevice& getDevice() const { return mStream->getDevice(); }
+    const AudioPortConfig& getDevicePortConfig() const { return mStream->getDevicePortConfig(); }
+    const std::vector<int8_t>& getLastData() const { return mLastData; }
+    const AudioPortConfig& getPortConfig() const { return mStream->getPortConfig(); }
     Stream* getStream() const { return mStream->getStream(); }
     std::string skipTestReason() const {
         return !mSkipTestReason.empty() ? mSkipTestReason : mStream->skipTestReason();
@@ -3162,6 +3298,7 @@
     std::unique_ptr<StreamFixture<Stream>> mStream;
     std::unique_ptr<StreamLogicDefaultDriver> mWorkerDriver;
     std::unique_ptr<typename IOTraits<Stream>::Worker> mWorker;
+    std::vector<int8_t> mLastData;
 };
 
 template <typename Stream>
@@ -3879,11 +4016,6 @@
             AudioPlaybackRate{1.0f, 1.0f, tsVoice, fbFail},
             AudioPlaybackRate{factors.maxSpeed, factors.maxPitch, tsVoice, fbMute},
             AudioPlaybackRate{factors.minSpeed, factors.minPitch, tsVoice, fbMute},
-            // Out of range speed / pitch values must not be rejected if the fallback mode is "mute"
-            AudioPlaybackRate{factors.maxSpeed * 2, factors.maxPitch * 2, tsDefault, fbMute},
-            AudioPlaybackRate{factors.minSpeed / 2, factors.minPitch / 2, tsDefault, fbMute},
-            AudioPlaybackRate{factors.maxSpeed * 2, factors.maxPitch * 2, tsVoice, fbMute},
-            AudioPlaybackRate{factors.minSpeed / 2, factors.minPitch / 2, tsVoice, fbMute},
     };
     const std::vector<AudioPlaybackRate> invalidValues = {
             AudioPlaybackRate{factors.maxSpeed, factors.maxPitch * 2, tsDefault, fbFail},
@@ -3899,6 +4031,14 @@
             AudioPlaybackRate{1.0f, 1.0f, tsDefault,
                               AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT},
     };
+    const std::vector<AudioPlaybackRate> ambivalentValues = {
+            // Out of range speed / pitch values may optionally be rejected if the fallback mode
+            // is "mute".
+            AudioPlaybackRate{factors.maxSpeed * 2, factors.maxPitch * 2, tsDefault, fbMute},
+            AudioPlaybackRate{factors.minSpeed / 2, factors.minPitch / 2, tsDefault, fbMute},
+            AudioPlaybackRate{factors.maxSpeed * 2, factors.maxPitch * 2, tsVoice, fbMute},
+            AudioPlaybackRate{factors.minSpeed / 2, factors.minPitch / 2, tsVoice, fbMute},
+    };
     bool atLeastOneSupports = false;
     for (const auto& port : offloadMixPorts) {
         const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
@@ -3908,7 +4048,8 @@
         bool isSupported = false;
         EXPECT_NO_FATAL_FAILURE(TestAccessors<AudioPlaybackRate>(
                 stream.get(), &IStreamOut::getPlaybackRateParameters,
-                &IStreamOut::setPlaybackRateParameters, validValues, invalidValues, &isSupported));
+                &IStreamOut::setPlaybackRateParameters, validValues, invalidValues, &isSupported,
+                &ambivalentValues));
         if (isSupported) atLeastOneSupports = true;
     }
     if (!atLeastOneSupports) {
@@ -3968,6 +4109,7 @@
 
 enum {
     NAMED_CMD_NAME,
+    NAMED_CMD_MIN_INTERFACE_VERSION,
     NAMED_CMD_DELAY_MS,
     NAMED_CMD_STREAM_TYPE,
     NAMED_CMD_CMDS,
@@ -3975,7 +4117,7 @@
 };
 enum class StreamTypeFilter { ANY, SYNC, ASYNC };
 using NamedCommandSequence =
-        std::tuple<std::string, int /*cmdDelayMs*/, StreamTypeFilter,
+        std::tuple<std::string, int /*minInterfaceVersion*/, int /*cmdDelayMs*/, StreamTypeFilter,
                    std::shared_ptr<StateSequence>, bool /*validatePositionIncrease*/>;
 enum { PARAM_MODULE_NAME, PARAM_CMD_SEQ, PARAM_SETUP_SEQ };
 using StreamIoTestParameters =
@@ -3986,6 +4128,12 @@
   public:
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(SetUpImpl(std::get<PARAM_MODULE_NAME>(GetParam())));
+        ASSERT_GE(aidlVersion, kAidlVersion1);
+        if (const int minVersion =
+                    std::get<NAMED_CMD_MIN_INTERFACE_VERSION>(std::get<PARAM_CMD_SEQ>(GetParam()));
+            aidlVersion < minVersion) {
+            GTEST_SKIP() << "Skip for audio HAL version lower than " << minVersion;
+        }
         ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
     }
 
@@ -3995,6 +4143,20 @@
         if (allPortConfigs.empty()) {
             GTEST_SKIP() << "No mix ports have attached devices";
         }
+        const auto& commandsAndStates =
+                std::get<NAMED_CMD_CMDS>(std::get<PARAM_CMD_SEQ>(GetParam()));
+        const bool validatePositionIncrease =
+                std::get<NAMED_CMD_VALIDATE_POS_INCREASE>(std::get<PARAM_CMD_SEQ>(GetParam()));
+        auto runStreamIoCommands = [&](const AudioPortConfig& portConfig) {
+            if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
+                ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates,
+                                                                    validatePositionIncrease));
+            } else {
+                ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates,
+                                                                    validatePositionIncrease));
+            }
+        };
+
         for (const auto& portConfig : allPortConfigs) {
             auto port = moduleConfig->getPort(portConfig.portId);
             ASSERT_TRUE(port.has_value());
@@ -4022,16 +4184,18 @@
             delayTransientStates.flags().streamTransientStateDelayMs =
                     std::get<NAMED_CMD_DELAY_MS>(std::get<PARAM_CMD_SEQ>(GetParam()));
             ASSERT_NO_FATAL_FAILURE(delayTransientStates.SetUp(module.get()));
-            const auto& commandsAndStates =
-                    std::get<NAMED_CMD_CMDS>(std::get<PARAM_CMD_SEQ>(GetParam()));
-            const bool validatePositionIncrease =
-                    std::get<NAMED_CMD_VALIDATE_POS_INCREASE>(std::get<PARAM_CMD_SEQ>(GetParam()));
-            if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
-                ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates,
-                                                                    validatePositionIncrease));
-            } else {
-                ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates,
-                                                                    validatePositionIncrease));
+            ASSERT_NO_FATAL_FAILURE(runStreamIoCommands(portConfig));
+            if (aidlVersion >= kAidlVersion3 && isNonBlocking && !IOTraits<Stream>::is_input) {
+                // Also try running the same sequence with "aosp.forceDrainToDraining" set.
+                // This will only work with the default implementation. When it works, the stream
+                // tries always to move to the 'DRAINING' state after an "early notify" drain.
+                // This helps to check more paths for our test scenarios.
+                WithModuleParameter forceDrainToDraining("aosp.forceDrainToDraining",
+                                                         Boolean{true});
+                if (forceDrainToDraining.SetUpNoChecks(module.get(), true /*failureExpected*/)
+                            .isOk()) {
+                    ASSERT_NO_FATAL_FAILURE(runStreamIoCommands(portConfig));
+                }
             }
             if (isNonBlocking) {
                 // Also try running the same sequence with "aosp.forceTransientBurst" set.
@@ -4041,13 +4205,7 @@
                 WithModuleParameter forceTransientBurst("aosp.forceTransientBurst", Boolean{true});
                 if (forceTransientBurst.SetUpNoChecks(module.get(), true /*failureExpected*/)
                             .isOk()) {
-                    if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
-                        ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(
-                                portConfig, commandsAndStates, validatePositionIncrease));
-                    } else {
-                        ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(
-                                portConfig, commandsAndStates, validatePositionIncrease));
-                    }
+                    ASSERT_NO_FATAL_FAILURE(runStreamIoCommands(portConfig));
                 }
             } else if (!IOTraits<Stream>::is_input) {
                 // Also try running the same sequence with "aosp.forceSynchronousDrain" set.
@@ -4058,13 +4216,7 @@
                                                           Boolean{true});
                 if (forceSynchronousDrain.SetUpNoChecks(module.get(), true /*failureExpected*/)
                             .isOk()) {
-                    if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
-                        ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(
-                                portConfig, commandsAndStates, validatePositionIncrease));
-                    } else {
-                        ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(
-                                portConfig, commandsAndStates, validatePositionIncrease));
-                    }
+                    ASSERT_NO_FATAL_FAILURE(runStreamIoCommands(portConfig));
                 }
             }
         }
@@ -4494,15 +4646,20 @@
 
 // TODO: Add async test cases for input once it is implemented.
 
-std::shared_ptr<StateSequence> makeBurstCommands(bool isSync) {
+std::shared_ptr<StateSequence> makeBurstCommands(bool isSync, size_t burstCount,
+                                                 bool standbyInputWhenDone) {
     using State = StreamDescriptor::State;
     auto d = std::make_unique<StateDag>();
-    StateDag::Node last = d->makeFinalNode(State::ACTIVE);
+    StateDag::Node active = d->makeFinalNode(State::ACTIVE);
+    StateDag::Node paused = d->makeNodes({std::make_pair(State::ACTIVE, kPauseCommand),
+                                          std::make_pair(State::PAUSED, kFlushCommand)},
+                                         State::STANDBY);
+    StateDag::Node& last = standbyInputWhenDone ? paused : active;
     if (isSync) {
         StateDag::Node idle = d->makeNode(
                 State::IDLE, kBurstCommand,
                 // Use several bursts to ensure that the driver starts reporting the position.
-                d->makeNodes(State::ACTIVE, kBurstCommand, 10, last));
+                d->makeNodes(State::ACTIVE, kBurstCommand, burstCount, last));
         d->makeNode(State::STANDBY, kStartCommand, idle);
     } else {
         StateDag::Node active2 = d->makeNode(State::ACTIVE, kBurstCommand, last);
@@ -4517,14 +4674,14 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kReadSeq =
-        std::make_tuple(std::string("Read"), 0, StreamTypeFilter::ANY, makeBurstCommands(true),
-                        true /*validatePositionIncrease*/);
+        std::make_tuple(std::string("Read"), kAidlVersion1, 0, StreamTypeFilter::ANY,
+                        makeBurstCommands(true), true /*validatePositionIncrease*/);
 static const NamedCommandSequence kWriteSyncSeq =
-        std::make_tuple(std::string("Write"), 0, StreamTypeFilter::SYNC, makeBurstCommands(true),
-                        true /*validatePositionIncrease*/);
+        std::make_tuple(std::string("Write"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
+                        makeBurstCommands(true), true /*validatePositionIncrease*/);
 static const NamedCommandSequence kWriteAsyncSeq =
-        std::make_tuple(std::string("Write"), 0, StreamTypeFilter::ASYNC, makeBurstCommands(false),
-                        true /*validatePositionIncrease*/);
+        std::make_tuple(std::string("Write"), kAidlVersion1, 0, StreamTypeFilter::ASYNC,
+                        makeBurstCommands(false), true /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeAsyncDrainCommands(bool isInput) {
     using State = StreamDescriptor::State;
@@ -4553,10 +4710,10 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kWriteDrainAsyncSeq = std::make_tuple(
-        std::string("WriteDrain"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
-        makeAsyncDrainCommands(false), false /*validatePositionIncrease*/);
+        std::string("WriteDrain"), kAidlVersion1, kStreamTransientStateTransitionDelayMs,
+        StreamTypeFilter::ASYNC, makeAsyncDrainCommands(false), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kDrainInSeq =
-        std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::ANY,
+        std::make_tuple(std::string("Drain"), kAidlVersion1, 0, StreamTypeFilter::ANY,
                         makeAsyncDrainCommands(true), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeDrainOutCommands(bool isSync) {
@@ -4578,12 +4735,28 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kDrainOutSyncSeq =
-        std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::SYNC, makeDrainOutCommands(true),
-                        false /*validatePositionIncrease*/);
+        std::make_tuple(std::string("Drain"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
+                        makeDrainOutCommands(true), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kDrainOutAsyncSeq =
-        std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::ASYNC,
+        std::make_tuple(std::string("Drain"), kAidlVersion3, 0, StreamTypeFilter::ASYNC,
                         makeDrainOutCommands(false), false /*validatePositionIncrease*/);
 
+std::shared_ptr<StateSequence> makeDrainEarlyOutCommands() {
+    using State = StreamDescriptor::State;
+    auto d = std::make_unique<StateDag>();
+    StateDag::Node last = d->makeFinalNode(State::IDLE);
+    StateDag::Node draining = d->makeNode(State::DRAINING, kDrainReadyEvent, last);
+    draining.children().push_back(d->makeNode(State::DRAINING, kGetStatusCommand, last));
+    StateDag::Node active = d->makeNode(State::ACTIVE, kDrainOutEarlyCommand, draining);
+    StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
+    idle.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active));
+    d->makeNode(State::STANDBY, kStartCommand, idle);
+    return std::make_shared<StateSequenceFollower>(std::move(d));
+}
+static const NamedCommandSequence kDrainEarlyOutAsyncSeq =
+        std::make_tuple(std::string("DrainEarly"), kAidlVersion3, 0, StreamTypeFilter::ASYNC,
+                        makeDrainEarlyOutCommands(), false /*validatePositionIncrease*/);
+
 std::shared_ptr<StateSequence> makeDrainPauseOutCommands(bool isSync) {
     using State = StreamDescriptor::State;
     auto d = std::make_unique<StateDag>();
@@ -4603,12 +4776,33 @@
     d->makeNode(State::STANDBY, kStartCommand, idle);
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kDrainPauseOutSyncSeq = std::make_tuple(
-        std::string("DrainPause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::SYNC,
-        makeDrainPauseOutCommands(true), false /*validatePositionIncrease*/);
-static const NamedCommandSequence kDrainPauseOutAsyncSeq = std::make_tuple(
-        std::string("DrainPause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
-        makeDrainPauseOutCommands(false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kDrainPauseOutSyncSeq =
+        std::make_tuple(std::string("DrainPause"), kAidlVersion1,
+                        kStreamTransientStateTransitionDelayMs, StreamTypeFilter::SYNC,
+                        makeDrainPauseOutCommands(true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kDrainPauseOutAsyncSeq =
+        std::make_tuple(std::string("DrainPause"), kAidlVersion1,
+                        kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+                        makeDrainPauseOutCommands(false), false /*validatePositionIncrease*/);
+
+std::shared_ptr<StateSequence> makeDrainEarlyPauseOutCommands() {
+    using State = StreamDescriptor::State;
+    auto d = std::make_unique<StateDag>();
+    StateDag::Node draining = d->makeNodes({std::make_pair(State::DRAINING, kPauseCommand),
+                                            std::make_pair(State::DRAIN_PAUSED, kStartCommand),
+                                            std::make_pair(State::DRAINING, kPauseCommand),
+                                            std::make_pair(State::DRAIN_PAUSED, kBurstCommand)},
+                                           State::TRANSFER_PAUSED);
+    StateDag::Node active = d->makeNode(State::ACTIVE, kDrainOutEarlyCommand, draining);
+    StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
+    idle.children().push_back(d->makeNode(State::TRANSFERRING, kDrainOutEarlyCommand, draining));
+    d->makeNode(State::STANDBY, kStartCommand, idle);
+    return std::make_shared<StateSequenceFollower>(std::move(d));
+}
+static const NamedCommandSequence kDrainEarlyPauseOutAsyncSeq =
+        std::make_tuple(std::string("DrainEarlyPause"), kAidlVersion3,
+                        kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+                        makeDrainEarlyPauseOutCommands(), false /*validatePositionIncrease*/);
 
 // This sequence also verifies that the capture / presentation position is not reset on standby.
 std::shared_ptr<StateSequence> makeStandbyCommands(bool isInput, bool isSync) {
@@ -4650,14 +4844,15 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kStandbyInSeq =
-        std::make_tuple(std::string("Standby"), 0, StreamTypeFilter::ANY,
+        std::make_tuple(std::string("Standby"), kAidlVersion1, 0, StreamTypeFilter::ANY,
                         makeStandbyCommands(true, false), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kStandbyOutSyncSeq =
-        std::make_tuple(std::string("Standby"), 0, StreamTypeFilter::SYNC,
+        std::make_tuple(std::string("Standby"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
                         makeStandbyCommands(false, true), false /*validatePositionIncrease*/);
-static const NamedCommandSequence kStandbyOutAsyncSeq = std::make_tuple(
-        std::string("Standby"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
-        makeStandbyCommands(false, false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kStandbyOutAsyncSeq =
+        std::make_tuple(std::string("Standby"), kAidlVersion1,
+                        kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+                        makeStandbyCommands(false, false), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makePauseCommands(bool isInput, bool isSync) {
     using State = StreamDescriptor::State;
@@ -4692,14 +4887,15 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kPauseInSeq =
-        std::make_tuple(std::string("Pause"), 0, StreamTypeFilter::ANY,
+        std::make_tuple(std::string("Pause"), kAidlVersion1, 0, StreamTypeFilter::ANY,
                         makePauseCommands(true, false), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kPauseOutSyncSeq =
-        std::make_tuple(std::string("Pause"), 0, StreamTypeFilter::SYNC,
+        std::make_tuple(std::string("Pause"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
                         makePauseCommands(false, true), false /*validatePositionIncrease*/);
-static const NamedCommandSequence kPauseOutAsyncSeq = std::make_tuple(
-        std::string("Pause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
-        makePauseCommands(false, false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kPauseOutAsyncSeq =
+        std::make_tuple(std::string("Pause"), kAidlVersion1, kStreamTransientStateTransitionDelayMs,
+                        StreamTypeFilter::ASYNC, makePauseCommands(false, false),
+                        false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeFlushCommands(bool isInput, bool isSync) {
     using State = StreamDescriptor::State;
@@ -4727,14 +4923,15 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kFlushInSeq =
-        std::make_tuple(std::string("Flush"), 0, StreamTypeFilter::ANY,
+        std::make_tuple(std::string("Flush"), kAidlVersion1, 0, StreamTypeFilter::ANY,
                         makeFlushCommands(true, false), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kFlushOutSyncSeq =
-        std::make_tuple(std::string("Flush"), 0, StreamTypeFilter::SYNC,
+        std::make_tuple(std::string("Flush"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
                         makeFlushCommands(false, true), false /*validatePositionIncrease*/);
-static const NamedCommandSequence kFlushOutAsyncSeq = std::make_tuple(
-        std::string("Flush"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
-        makeFlushCommands(false, false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kFlushOutAsyncSeq =
+        std::make_tuple(std::string("Flush"), kAidlVersion1, kStreamTransientStateTransitionDelayMs,
+                        StreamTypeFilter::ASYNC, makeFlushCommands(false, false),
+                        false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeDrainPauseFlushOutCommands(bool isSync) {
     using State = StreamDescriptor::State;
@@ -4754,13 +4951,13 @@
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kDrainPauseFlushOutSyncSeq =
-        std::make_tuple(std::string("DrainPauseFlush"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::SYNC, makeDrainPauseFlushOutCommands(true),
-                        false /*validatePositionIncrease*/);
+        std::make_tuple(std::string("DrainPauseFlush"), kAidlVersion1,
+                        kStreamTransientStateTransitionDelayMs, StreamTypeFilter::SYNC,
+                        makeDrainPauseFlushOutCommands(true), false /*validatePositionIncrease*/);
 static const NamedCommandSequence kDrainPauseFlushOutAsyncSeq =
-        std::make_tuple(std::string("DrainPauseFlush"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makeDrainPauseFlushOutCommands(false),
-                        false /*validatePositionIncrease*/);
+        std::make_tuple(std::string("DrainPauseFlush"), kAidlVersion1,
+                        kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+                        makeDrainPauseFlushOutCommands(false), false /*validatePositionIncrease*/);
 
 // Note, this isn't the "official" enum printer, it is only used to make the test name suffix.
 std::string PrintStreamFilterToString(StreamTypeFilter filter) {
@@ -4798,9 +4995,10 @@
         AudioStreamIoOutTest, AudioStreamIoOut,
         testing::Combine(testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
                          testing::Values(kWriteSyncSeq, kWriteAsyncSeq, kWriteDrainAsyncSeq,
-                                         kDrainOutSyncSeq, kDrainPauseOutSyncSeq,
-                                         kDrainPauseOutAsyncSeq, kStandbyOutSyncSeq,
-                                         kStandbyOutAsyncSeq,
+                                         kDrainOutSyncSeq, kDrainOutAsyncSeq,
+                                         kDrainEarlyOutAsyncSeq, kDrainPauseOutSyncSeq,
+                                         kDrainPauseOutAsyncSeq, kDrainEarlyPauseOutAsyncSeq,
+                                         kStandbyOutSyncSeq, kStandbyOutAsyncSeq,
                                          kPauseOutSyncSeq,  // kPauseOutAsyncSeq,
                                          kFlushOutSyncSeq, kFlushOutAsyncSeq,
                                          kDrainPauseFlushOutSyncSeq, kDrainPauseFlushOutAsyncSeq),
@@ -4826,49 +5024,69 @@
   public:
     WithRemoteSubmix() : mStream(true /*isSync*/) {}
     explicit WithRemoteSubmix(AudioDeviceAddress address)
-        : mStream(true /*isSync*/), mAddress(address) {}
+        : mStream(true /*isSync*/), mAddress(address) {
+        LOG(DEBUG) << __func__ << ": Creating " << IOTraits<Stream>::directionStr
+                   << " stream for: " << mAddress.value_or(AudioDeviceAddress{}).toString();
+    }
     WithRemoteSubmix(const WithRemoteSubmix&) = delete;
     WithRemoteSubmix& operator=(const WithRemoteSubmix&) = delete;
+    ~WithRemoteSubmix() {
+        LOG(DEBUG) << __func__ << ": Deleting " << IOTraits<Stream>::directionStr
+                   << " stream for: " << mAddress.value_or(AudioDeviceAddress{}).toString();
+    }
 
-    static std::optional<AudioPort> getRemoteSubmixAudioPort(
-            ModuleConfig* moduleConfig,
-            const std::optional<AudioDeviceAddress>& address = std::nullopt) {
+    static std::optional<AudioPort> getRemoteSubmixAudioPort(ModuleConfig* moduleConfig) {
         auto ports =
                 moduleConfig->getRemoteSubmixPorts(IOTraits<Stream>::is_input, true /*singlePort*/);
         if (ports.empty()) return {};
-        AudioPort port = ports.front();
-        if (address) {
-            port.ext.template get<AudioPortExt::Tag::device>().device.address = address.value();
-        }
-        return port;
+        return ports.front();
     }
 
     void SetUp(IModule* module, ModuleConfig* moduleConfig) {
-        auto devicePort = getRemoteSubmixAudioPort(moduleConfig, mAddress);
+        auto devicePort = getRemoteSubmixAudioPort(moduleConfig);
         ASSERT_TRUE(devicePort.has_value()) << "Device port for remote submix device not found";
-        ASSERT_NO_FATAL_FAILURE(mStream.SetUp(module, moduleConfig, *devicePort));
+        ASSERT_NO_FATAL_FAILURE(mStream.SetUp(module, moduleConfig, *devicePort, mAddress));
         mAddress = mStream.getDevice().address;
     }
-
-    void StartWorkerToSendBurstCommands() {
-        ASSERT_NO_FATAL_FAILURE(mStream.StartWorkerToSendBurstCommands());
+    void SetUp(IModule* module, ModuleConfig* moduleConfig,
+               const AudioPortConfig& existingMixPortConfig,
+               const AudioPortConfig& existingDevicePortConfig) {
+        ASSERT_NO_FATAL_FAILURE(mStream.SetUp(module, moduleConfig, existingMixPortConfig,
+                                              existingDevicePortConfig));
+        mAddress = mStream.getDevice().address;
+    }
+    void StartWorkerToSendBurstCommands(size_t burstCount = 10, bool standbyInputWhenDone = false) {
+        ASSERT_NO_FATAL_FAILURE(
+                mStream.StartWorkerToSendBurstCommands(burstCount, standbyInputWhenDone));
     }
 
-    void JoinWorkerAfterBurstCommands() {
-        ASSERT_NO_FATAL_FAILURE(mStream.JoinWorkerAfterBurstCommands());
+    void JoinWorkerAfterBurstCommands(bool callPrepareToCloseBeforeJoin) {
+        ASSERT_NO_FATAL_FAILURE(mStream.JoinWorkerAfterBurstCommands(
+                true /*validatePositionIncrease*/, callPrepareToCloseBeforeJoin));
     }
 
-    void SendBurstCommands() {
-        ASSERT_NO_FATAL_FAILURE(mStream.StartWorkerToSendBurstCommands());
-        ASSERT_NO_FATAL_FAILURE(mStream.JoinWorkerAfterBurstCommands());
+    void JoinWorkerAfterBurstCommands(bool validatePositionIncrease,
+                                      bool callPrepareToCloseBeforeJoin) {
+        ASSERT_NO_FATAL_FAILURE(mStream.JoinWorkerAfterBurstCommands(validatePositionIncrease,
+                                                                     callPrepareToCloseBeforeJoin));
+    }
+
+    void SendBurstCommands(bool callPrepareToCloseBeforeJoin, size_t burstCount = 10,
+                           bool standbyInputWhenDone = false) {
+        ASSERT_NO_FATAL_FAILURE(StartWorkerToSendBurstCommands(burstCount, standbyInputWhenDone));
+        // When 'burstCount == 0', there is no "previous" frame count, thus the check for
+        // the position increase fails.
+        ASSERT_NO_FATAL_FAILURE(JoinWorkerAfterBurstCommands(
+                burstCount > 0 /*validatePositionIncrease*/, callPrepareToCloseBeforeJoin));
     }
 
     std::optional<AudioDeviceAddress> getAudioDeviceAddress() const { return mAddress; }
+    const AudioPortConfig& getDevicePortConfig() const { return mStream.getDevicePortConfig(); }
+    int8_t getLastBurstIteration() const { return mStream.getLastData()[0]; }
+    const AudioPortConfig& getPortConfig() const { return mStream.getPortConfig(); }
     std::string skipTestReason() const { return mStream.skipTestReason(); }
 
   private:
-    void SetUp(IModule* module, ModuleConfig* moduleConfig, const AudioPort& devicePort) {}
-
     StreamFixtureWithWorker<Stream> mStream;
     std::optional<AudioDeviceAddress> mAddress;
 };
@@ -4884,77 +5102,130 @@
         }
         ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
     }
+
+    void TearDown() override {
+        streamIn.reset();
+        streamOut.reset();
+    }
+
+    void CreateOutputStream() {
+        streamOut = std::make_unique<WithRemoteSubmix<IStreamOut>>();
+        ASSERT_NO_FATAL_FAILURE(streamOut->SetUp(module.get(), moduleConfig.get()));
+        // Note: any issue with connection attempts is considered as a problem.
+        ASSERT_EQ("", streamOut->skipTestReason());
+        ASSERT_TRUE(streamOut->getAudioDeviceAddress().has_value());
+    }
+
+    void CreateInputStream(const std::optional<AudioDeviceAddress>& address = std::nullopt) {
+        if (address.has_value()) {
+            streamIn = std::make_unique<WithRemoteSubmix<IStreamIn>>(address.value());
+        } else {
+            ASSERT_TRUE(streamOut->getAudioDeviceAddress().has_value());
+            streamIn = std::make_unique<WithRemoteSubmix<IStreamIn>>(
+                    streamOut->getAudioDeviceAddress().value());
+        }
+        ASSERT_NO_FATAL_FAILURE(streamIn->SetUp(module.get(), moduleConfig.get()));
+        ASSERT_EQ("", streamIn->skipTestReason());
+        auto inAddress = streamIn->getAudioDeviceAddress();
+        ASSERT_TRUE(inAddress.has_value());
+        if (address.has_value()) {
+            if (address.value() != AudioDeviceAddress{}) {
+                ASSERT_EQ(address.value(), inAddress.value());
+            }
+        } else {
+            ASSERT_EQ(streamOut->getAudioDeviceAddress().value(), inAddress.value());
+        }
+    }
+
+    std::unique_ptr<WithRemoteSubmix<IStreamOut>> streamOut;
+    std::unique_ptr<WithRemoteSubmix<IStreamIn>> streamIn;
 };
 
 TEST_P(AudioModuleRemoteSubmix, OutputDoesNotBlockWhenNoInput) {
-    WithRemoteSubmix<IStreamOut> streamOut;
-    ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
-    // Note: here and in other tests any issue with connection attempts is considered as a problem.
-    ASSERT_EQ("", streamOut.skipTestReason());
-    ASSERT_NO_FATAL_FAILURE(streamOut.SendBurstCommands());
+    ASSERT_NO_FATAL_FAILURE(CreateOutputStream());
+    ASSERT_NO_FATAL_FAILURE(streamOut->SendBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
 }
 
-TEST_P(AudioModuleRemoteSubmix, OutputDoesNotBlockWhenInputStuck) {
-    WithRemoteSubmix<IStreamOut> streamOut;
-    ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
-    ASSERT_EQ("", streamOut.skipTestReason());
-    auto address = streamOut.getAudioDeviceAddress();
-    ASSERT_TRUE(address.has_value());
+TEST_P(AudioModuleRemoteSubmix, OutputDoesNotBlockWhenInputInStandby) {
+    if (int32_t version; module->getInterfaceVersion(&version).isOk() && version < 3) {
+        GTEST_SKIP() << "Default remote submix implementation <V3 could not pass this test";
+    }
+    ASSERT_NO_FATAL_FAILURE(CreateOutputStream());
+    ASSERT_NO_FATAL_FAILURE(CreateInputStream());
+    ASSERT_NO_FATAL_FAILURE(streamOut->StartWorkerToSendBurstCommands());
+    // Send just 1 burst command. This triggers the condition "input is in standby after
+    // being active." The output must flush the fifo before writing to avoid being blocked.
+    ASSERT_NO_FATAL_FAILURE(
+            streamIn->StartWorkerToSendBurstCommands(1, true /*stanbyInputWhenDone*/));
+    // The output must be able to close without shutting down the pipe first (due to a call
+    // to 'prepareToClose').
+    ASSERT_NO_FATAL_FAILURE(
+            streamOut->JoinWorkerAfterBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
+    ASSERT_NO_FATAL_FAILURE(
+            streamIn->JoinWorkerAfterBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
+}
 
-    WithRemoteSubmix<IStreamIn> streamIn(address.value());
-    ASSERT_NO_FATAL_FAILURE(streamIn.SetUp(module.get(), moduleConfig.get()));
-    ASSERT_EQ("", streamIn.skipTestReason());
+TEST_P(AudioModuleRemoteSubmix, BlockedOutputUnblocksOnClose) {
+    ASSERT_NO_FATAL_FAILURE(CreateOutputStream());
+    ASSERT_NO_FATAL_FAILURE(CreateInputStream());
+    ASSERT_NO_FATAL_FAILURE(streamOut->StartWorkerToSendBurstCommands());
+    // Send just 3 burst command, but do not enter standby. This is a stalled input.
+    ASSERT_NO_FATAL_FAILURE(streamIn->StartWorkerToSendBurstCommands(3));
+    ASSERT_NO_FATAL_FAILURE(
+            streamOut->JoinWorkerAfterBurstCommands(true /*callPrepareToCloseBeforeJoin*/));
+    ASSERT_NO_FATAL_FAILURE(
+            streamIn->JoinWorkerAfterBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
+}
 
-    ASSERT_NO_FATAL_FAILURE(streamOut.SendBurstCommands());
+TEST_P(AudioModuleRemoteSubmix, OutputBlocksUntilInputStarts) {
+    ASSERT_NO_FATAL_FAILURE(CreateOutputStream());
+    ASSERT_NO_FATAL_FAILURE(CreateInputStream());
+    ASSERT_NO_FATAL_FAILURE(streamOut->StartWorkerToSendBurstCommands());
+    // Read the head of the pipe and check that it starts with the first output burst, that is,
+    // the contents of the very first write has not been superseded due to pipe overflow.
+    // The burstCount is '0' because the very first burst is used to exit from the 'IDLE' state,
+    // see 'makeBurstCommands'.
+    ASSERT_NO_FATAL_FAILURE(streamIn->SendBurstCommands(false /*callPrepareToCloseBeforeJoin*/, 0,
+                                                        true /*standbyInputWhenDone*/));
+    EXPECT_EQ(1, streamIn->getLastBurstIteration());
+    ASSERT_NO_FATAL_FAILURE(
+            streamOut->JoinWorkerAfterBurstCommands(true /*callPrepareToCloseBeforeJoin*/));
 }
 
 TEST_P(AudioModuleRemoteSubmix, OutputAndInput) {
-    WithRemoteSubmix<IStreamOut> streamOut;
-    ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
-    ASSERT_EQ("", streamOut.skipTestReason());
-    auto address = streamOut.getAudioDeviceAddress();
-    ASSERT_TRUE(address.has_value());
-
-    WithRemoteSubmix<IStreamIn> streamIn(address.value());
-    ASSERT_NO_FATAL_FAILURE(streamIn.SetUp(module.get(), moduleConfig.get()));
-    ASSERT_EQ("", streamIn.skipTestReason());
-
+    ASSERT_NO_FATAL_FAILURE(CreateOutputStream());
+    ASSERT_NO_FATAL_FAILURE(CreateInputStream());
     // Start writing into the output stream.
-    ASSERT_NO_FATAL_FAILURE(streamOut.StartWorkerToSendBurstCommands());
+    ASSERT_NO_FATAL_FAILURE(streamOut->StartWorkerToSendBurstCommands());
     // Simultaneously, read from the input stream.
-    ASSERT_NO_FATAL_FAILURE(streamIn.SendBurstCommands());
-    ASSERT_NO_FATAL_FAILURE(streamOut.JoinWorkerAfterBurstCommands());
+    ASSERT_NO_FATAL_FAILURE(streamIn->SendBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
+    ASSERT_NO_FATAL_FAILURE(
+            streamOut->JoinWorkerAfterBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
 }
 
 TEST_P(AudioModuleRemoteSubmix, OpenInputMultipleTimes) {
-    WithRemoteSubmix<IStreamOut> streamOut;
-    ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
-    ASSERT_EQ("", streamOut.skipTestReason());
-    auto address = streamOut.getAudioDeviceAddress();
-    ASSERT_TRUE(address.has_value());
-
-    const size_t streamInCount = 3;
-    std::vector<std::unique_ptr<WithRemoteSubmix<IStreamIn>>> streamIns(streamInCount);
-    for (size_t i = 0; i < streamInCount; i++) {
-        streamIns[i] = std::make_unique<WithRemoteSubmix<IStreamIn>>(address.value());
-        ASSERT_NO_FATAL_FAILURE(streamIns[i]->SetUp(module.get(), moduleConfig.get()));
+    ASSERT_NO_FATAL_FAILURE(CreateOutputStream());
+    ASSERT_NO_FATAL_FAILURE(CreateInputStream());
+    ASSERT_NO_FATAL_FAILURE(streamOut->StartWorkerToSendBurstCommands());
+    ASSERT_NO_FATAL_FAILURE(streamIn->SendBurstCommands(false /*callPrepareToCloseBeforeJoin*/, 1,
+                                                        true /*standbyInputWhenDone*/));
+    // For the new stream, only create a new mix port config and a new patch.
+    const size_t extraStreamInCount = 2;
+    std::vector<std::unique_ptr<WithRemoteSubmix<IStreamIn>>> streamIns(extraStreamInCount);
+    for (size_t i = 0; i < extraStreamInCount; i++) {
+        streamIns[i] = std::make_unique<WithRemoteSubmix<IStreamIn>>();
+        ASSERT_NO_FATAL_FAILURE(streamIns[i]->SetUp(module.get(), moduleConfig.get(),
+                                                    streamIn->getPortConfig(),
+                                                    streamIn->getDevicePortConfig()));
         ASSERT_EQ("", streamIns[i]->skipTestReason());
+        const auto inAddress = streamIns[i]->getAudioDeviceAddress();
+        ASSERT_TRUE(inAddress.has_value());
+        ASSERT_EQ(streamOut->getAudioDeviceAddress().value(), inAddress.value());
+        ASSERT_NO_FATAL_FAILURE(streamIns[i]->SendBurstCommands(
+                false /*callPrepareToCloseBeforeJoin*/, 1, true /*standbyInputWhenDone*/));
     }
-    // Start writing into the output stream.
-    ASSERT_NO_FATAL_FAILURE(streamOut.StartWorkerToSendBurstCommands());
-    // Simultaneously, read from input streams.
-    for (size_t i = 0; i < streamInCount; i++) {
-        ASSERT_NO_FATAL_FAILURE(streamIns[i]->StartWorkerToSendBurstCommands());
-    }
-    for (size_t i = 0; i < streamInCount; i++) {
-        ASSERT_NO_FATAL_FAILURE(streamIns[i]->JoinWorkerAfterBurstCommands());
-    }
-    ASSERT_NO_FATAL_FAILURE(streamOut.JoinWorkerAfterBurstCommands());
-    // Clean up input streams in the reverse order because the device connection is owned
-    // by the first one.
-    for (size_t i = streamInCount; i != 0; --i) {
-        streamIns[i - 1].reset();
-    }
+    ASSERT_NO_FATAL_FAILURE(
+            streamOut->JoinWorkerAfterBurstCommands(false /*callPrepareToCloseBeforeJoin*/));
 }
 
 INSTANTIATE_TEST_SUITE_P(AudioModuleRemoteSubmixTest, AudioModuleRemoteSubmix,
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index d23bdc9..5b78981 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -42,6 +42,7 @@
 using aidl::android::hardware::audio::effect::Flags;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kDestroyAnyStateSupportedVersion;
 using aidl::android::hardware::audio::effect::Parameter;
 using aidl::android::hardware::audio::effect::State;
 using aidl::android::media::audio::common::AudioDeviceDescription;
@@ -316,28 +317,39 @@
     ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
 }
 
-// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed before
+// `kDestroyAnyStateSupportedVersion`.
+// For any version after `kDestroyAnyStateSupportedVersion`, expect `destroy` to always success.
 TEST_P(AudioEffectTest, DestroyOpenEffects) {
     ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
     ASSERT_NO_FATAL_FAILURE(open(mEffect));
-    ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
-
-    // cleanup
-    ASSERT_NO_FATAL_FAILURE(close(mEffect));
-    ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+    if (mVersion < kDestroyAnyStateSupportedVersion) {
+        ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
+        // cleanup
+        ASSERT_NO_FATAL_FAILURE(close(mEffect));
+        ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+    } else {
+        ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+    }
 }
 
-// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed before
+// `kDestroyAnyStateSupportedVersion`.
+// For any version after `kDestroyAnyStateSupportedVersion`, expect `destroy` to always success.
 TEST_P(AudioEffectTest, DestroyProcessingEffects) {
     ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
     ASSERT_NO_FATAL_FAILURE(open(mEffect));
     ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
-    ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
 
-    // cleanup
-    ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
-    ASSERT_NO_FATAL_FAILURE(close(mEffect));
-    ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+    if (mVersion < kDestroyAnyStateSupportedVersion) {
+        ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
+        // cleanup
+        ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+        ASSERT_NO_FATAL_FAILURE(close(mEffect));
+        ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+    } else {
+        ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+    }
 }
 
 TEST_P(AudioEffectTest, NormalSequenceStates) {
diff --git a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
index 5ce2a20..c3c1e9e 100644
--- a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
@@ -48,7 +48,7 @@
 
 class BassBoostEffectHelper : public EffectHelper {
   public:
-    void SetUpBassBoost(int32_t layout = AudioChannelLayout::LAYOUT_STEREO) {
+    void SetUpBassBoost(int32_t layout = kDefaultChannelLayout) {
         ASSERT_NE(nullptr, mFactory);
         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
         setFrameCounts(layout);
@@ -113,8 +113,7 @@
         }
     }
 
-    static constexpr int kSamplingFrequency = 44100;
-    static constexpr int kDurationMilliSec = 720;
+    static constexpr int kDurationMilliSec = 1440;
     static constexpr int kInputSize = kSamplingFrequency * kDurationMilliSec / 1000;
     long mInputFrameCount, mOutputFrameCount;
     std::shared_ptr<IFactory> mFactory;
@@ -188,37 +187,6 @@
         }
     }
 
-    // Generate multitone input between -1 to +1 using testFrequencies
-    void generateMultiTone(const std::vector<int>& testFrequencies, std::vector<float>& input) {
-        for (auto i = 0; i < kInputSize; i++) {
-            input[i] = 0;
-
-            for (size_t j = 0; j < testFrequencies.size(); j++) {
-                input[i] += sin(2 * M_PI * testFrequencies[j] * i / kSamplingFrequency);
-            }
-            input[i] /= testFrequencies.size();
-        }
-    }
-
-    // Use FFT transform to convert the buffer to frequency domain
-    // Compute its magnitude at binOffsets
-    std::vector<float> calculateMagnitude(const std::vector<float>& buffer,
-                                          const std::vector<int>& binOffsets) {
-        std::vector<float> fftInput(kNPointFFT);
-        PFFFT_Setup* inputHandle = pffft_new_setup(kNPointFFT, PFFFT_REAL);
-        pffft_transform_ordered(inputHandle, buffer.data(), fftInput.data(), nullptr,
-                                PFFFT_FORWARD);
-        pffft_destroy_setup(inputHandle);
-        std::vector<float> bufferMag(binOffsets.size());
-        for (size_t i = 0; i < binOffsets.size(); i++) {
-            size_t k = binOffsets[i];
-            bufferMag[i] = sqrt((fftInput[k * 2] * fftInput[k * 2]) +
-                                (fftInput[k * 2 + 1] * fftInput[k * 2 + 1]));
-        }
-
-        return bufferMag;
-    }
-
     // Calculate gain difference between low frequency and high frequency magnitude
     float calculateGainDiff(const std::vector<float>& inputMag,
                             const std::vector<float>& outputMag) {
@@ -231,7 +199,6 @@
         return gains[0] - gains[1];
     }
 
-    static constexpr int kNPointFFT = 16384;
     static constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
     std::set<int> mStrengthValues;
     int32_t mChannelLayout;
@@ -252,9 +219,12 @@
 
     roundToFreqCenteredToFftBin(testFrequencies, binOffsets);
 
-    generateMultiTone(testFrequencies, input);
+    // Generate multitone input
+    ASSERT_NO_FATAL_FAILURE(
+            generateSineWave(testFrequencies, input, 1.0, kSamplingFrequency, mChannelLayout));
 
-    inputMag = calculateMagnitude(input, binOffsets);
+    ASSERT_NO_FATAL_FAILURE(
+            calculateAndVerifyMagnitude(inputMag, mChannelLayout, input, binOffsets));
 
     if (isStrengthValid(0)) {
         ASSERT_NO_FATAL_FAILURE(setAndVerifyParameters(0, EX_NONE));
@@ -266,7 +236,10 @@
             processAndWriteToOutput(input, baseOutput, mEffect, &mOpenEffectReturn));
 
     std::vector<float> baseMag(testFrequencies.size());
-    baseMag = calculateMagnitude(baseOutput, binOffsets);
+
+    ASSERT_NO_FATAL_FAILURE(
+            calculateAndVerifyMagnitude(baseMag, mChannelLayout, baseOutput, binOffsets));
+
     float baseDiff = calculateGainDiff(inputMag, baseMag);
 
     for (int strength : mStrengthValues) {
@@ -283,7 +256,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 processAndWriteToOutput(input, output, mEffect, &mOpenEffectReturn));
 
-        outputMag = calculateMagnitude(output, binOffsets);
+        ASSERT_NO_FATAL_FAILURE(
+                calculateAndVerifyMagnitude(outputMag, mChannelLayout, output, binOffsets));
+
         float diff = calculateGainDiff(inputMag, outputMag);
 
         ASSERT_GT(diff, prevGain);
diff --git a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
index a1491e6..5c5be3a 100644
--- a/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalDownmixTargetTest.cpp
@@ -52,7 +52,7 @@
         AudioChannelLayout::LAYOUT_5POINT1POINT4, AudioChannelLayout::LAYOUT_6POINT1,
         AudioChannelLayout::LAYOUT_7POINT1,       AudioChannelLayout::LAYOUT_7POINT1POINT2,
         AudioChannelLayout::LAYOUT_7POINT1POINT4, AudioChannelLayout::LAYOUT_9POINT1POINT4,
-        AudioChannelLayout::LAYOUT_9POINT1POINT6, AudioChannelLayout::LAYOUT_13POINT_360RA,
+        AudioChannelLayout::LAYOUT_9POINT1POINT6, AudioChannelLayout::LAYOUT_13POINT0,
         AudioChannelLayout::LAYOUT_22POINT2};
 
 static const std::vector<int32_t> kChannels = {
@@ -86,7 +86,7 @@
 
 class DownmixEffectHelper : public EffectHelper {
   public:
-    void SetUpDownmix(int32_t inputBufferLayout = AudioChannelLayout::LAYOUT_STEREO) {
+    void SetUpDownmix(int32_t inputBufferLayout = kDefaultChannelLayout) {
         ASSERT_NE(nullptr, mFactory);
         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
@@ -149,22 +149,6 @@
         mOutputBuffer.resize(mOutputBufferSize);
     }
 
-    // Generate mInputBuffer values between -kMaxDownmixSample to kMaxDownmixSample
-    void generateInputBuffer(size_t position, bool isStrip) {
-        size_t increment;
-        if (isStrip)
-            // Fill input at all the channels
-            increment = 1;
-        else
-            // Fill input at only one channel
-            increment = mInputChannelCount;
-
-        for (size_t i = position; i < mInputBuffer.size(); i += increment) {
-            mInputBuffer[i] =
-                    ((static_cast<float>(std::rand()) / RAND_MAX) * 2 - 1) * kMaxDownmixSample;
-        }
-    }
-
     bool isLayoutValid(int32_t inputLayout) {
         if (inputLayout & kMaxChannelMask) {
             return false;
@@ -365,7 +349,8 @@
 
     for (int32_t channel : supportedChannels) {
         size_t position = std::distance(supportedChannels.begin(), supportedChannels.find(channel));
-        generateInputBuffer(position, false /*isStripe*/);
+        generateInputBuffer(mInputBuffer, position, false /*isStripe*/,
+                            mInputChannelCount /*channelCount*/, kMaxDownmixSample);
         ASSERT_NO_FATAL_FAILURE(
                 processAndWriteToOutput(mInputBuffer, mOutputBuffer, mEffect, &mOpenEffectReturn));
         validateOutput(channel, position);
@@ -417,7 +402,8 @@
     ASSERT_NO_FATAL_FAILURE(setParameters(Downmix::Type::STRIP));
 
     // Generate input buffer, call process and compare outputs
-    generateInputBuffer(0 /*position*/, true /*isStripe*/);
+    generateInputBuffer(mInputBuffer, 0 /*position*/, true /*isStripe*/,
+                        mInputChannelCount /*channelCount*/, kMaxDownmixSample);
     ASSERT_NO_FATAL_FAILURE(
             processAndWriteToOutput(mInputBuffer, mOutputBuffer, mEffect, &mOpenEffectReturn));
     validateOutput();
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
index 0c201cc..09b6621 100644
--- a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
+++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
@@ -20,6 +20,8 @@
 
 #define LOG_TAG "VtsHalDynamicsProcessingTest"
 #include <android-base/logging.h>
+#include <audio_utils/power.h>
+#include <audio_utils/primitives.h>
 
 #include <Utils.h>
 
@@ -44,26 +46,25 @@
 class DynamicsProcessingTestHelper : public EffectHelper {
   public:
     DynamicsProcessingTestHelper(std::pair<std::shared_ptr<IFactory>, Descriptor> pair,
-                                 int32_t channelLayOut = AudioChannelLayout::LAYOUT_STEREO) {
+                                 int32_t channelLayout = kDefaultChannelLayout)
+        : mChannelLayout(channelLayout),
+          mChannelCount(::aidl::android::hardware::audio::common::getChannelCount(
+                  AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout))) {
         std::tie(mFactory, mDescriptor) = pair;
-        mChannelLayout = channelLayOut;
-        mChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
-                AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout));
     }
 
     // setup
     void SetUpDynamicsProcessingEffect() {
         ASSERT_NE(nullptr, mFactory);
         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
-
         Parameter::Specific specific = getDefaultParamSpecific();
         Parameter::Common common = createParamCommon(
-                0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
-                0x100 /* iFrameCount */, 0x100 /* oFrameCount */,
+                0 /* session */, 1 /* ioHandle */, kSamplingFrequency /* iSampleRate */,
+                kSamplingFrequency /* oSampleRate */, kFrameCount /* iFrameCount */,
+                kFrameCount /* oFrameCount */,
                 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout),
                 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout));
-        IEffect::OpenEffectReturn ret;
-        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
+        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE));
         ASSERT_NE(nullptr, mEffect);
         mEngineConfigApplied = mEngineConfigPreset;
     }
@@ -113,6 +114,12 @@
     // get set params and validate
     void SetAndGetDynamicsProcessingParameters();
 
+    bool isAllParamsValid();
+
+    void setParamsAndProcess(std::vector<float>& input, std::vector<float>& output);
+
+    float calculateDb(const std::vector<float>& input, size_t startSamplePos);
+
     // enqueue test parameters
     void addEngineConfig(const DynamicsProcessing::EngineArchitecture& cfg);
     void addPreEqChannelConfig(const std::vector<DynamicsProcessing::ChannelConfig>& cfg);
@@ -126,9 +133,15 @@
 
     static constexpr float kPreferredProcessingDurationMs = 10.0f;
     static constexpr int kBandCount = 5;
+    static constexpr int kSamplingFrequency = 44100;
+    static constexpr int kFrameCount = 2048;
+    static constexpr int kInputFrequency = 1000;
+    static constexpr size_t kStartIndex = 15 * kSamplingFrequency / 1000;  // skip 15ms
+    static constexpr float kToleranceDb = 0.05;
     std::shared_ptr<IFactory> mFactory;
     std::shared_ptr<IEffect> mEffect;
     Descriptor mDescriptor;
+    IEffect::OpenEffectReturn mOpenEffectReturn;
     DynamicsProcessing::EngineArchitecture mEngineConfigApplied;
     DynamicsProcessing::EngineArchitecture mEngineConfigPreset{
             .resolutionPreference =
@@ -148,12 +161,13 @@
     static const std::set<DynamicsProcessing::StageEnablement> kStageEnablementTestSet;
     static const std::set<std::vector<DynamicsProcessing::InputGain>> kInputGainTestSet;
 
-  protected:
-    int mChannelCount;
-
   private:
-    int32_t mChannelLayout;
     std::vector<std::pair<DynamicsProcessing::Tag, DynamicsProcessing>> mTags;
+
+  protected:
+    const int32_t mChannelLayout;
+    const int mChannelCount;
+
     void CleanUp() {
         mTags.clear();
         mPreEqChannelEnable.clear();
@@ -329,10 +343,7 @@
 }
 
 void DynamicsProcessingTestHelper::SetAndGetDynamicsProcessingParameters() {
-    for (auto& it : mTags) {
-        auto& tag = it.first;
-        auto& dp = it.second;
-
+    for (const auto& [tag, dp] : mTags) {
         // validate parameter
         Descriptor desc;
         ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
@@ -371,6 +382,40 @@
     }
 }
 
+bool DynamicsProcessingTestHelper::isAllParamsValid() {
+    if (mTags.empty()) {
+        return false;
+    }
+    for (const auto& [tag, dp] : mTags) {
+        // validate parameter
+        if (!isParamInRange(dp, mDescriptor.capability.range.get<Range::dynamicsProcessing>())) {
+            return false;
+        }
+        if (!isParamValid(tag, dp)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+// This function calculates power for both and mono and stereo data as the total power for
+// interleaved multichannel data can be calculated by treating it as a continuous mono input.
+float DynamicsProcessingTestHelper::calculateDb(const std::vector<float>& input,
+                                                size_t startSamplePos = 0) {
+    return audio_utils_compute_power_mono(input.data() + startSamplePos, AUDIO_FORMAT_PCM_FLOAT,
+                                          input.size() - startSamplePos);
+}
+
+void DynamicsProcessingTestHelper::setParamsAndProcess(std::vector<float>& input,
+                                                       std::vector<float>& output) {
+    ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
+    if (isAllParamsValid()) {
+        ASSERT_NO_FATAL_FAILURE(
+                processAndWriteToOutput(input, output, mEffect, &mOpenEffectReturn));
+        ASSERT_GT(output.size(), kStartIndex);
+    }
+}
+
 void DynamicsProcessingTestHelper::addEngineConfig(
         const DynamicsProcessing::EngineArchitecture& cfg) {
     DynamicsProcessing dp;
@@ -446,6 +491,21 @@
     mTags.push_back({DynamicsProcessing::inputGain, dp});
 }
 
+void fillLimiterConfig(std::vector<DynamicsProcessing::LimiterConfig>& limiterConfigList,
+                       int channelIndex, bool enable, int linkGroup, float attackTime,
+                       float releaseTime, float ratio, float threshold, float postGain) {
+    DynamicsProcessing::LimiterConfig cfg;
+    cfg.channel = channelIndex;
+    cfg.enable = enable;
+    cfg.linkGroup = linkGroup;
+    cfg.attackTimeMs = attackTime;
+    cfg.releaseTimeMs = releaseTime;
+    cfg.ratio = ratio;
+    cfg.thresholdDb = threshold;
+    cfg.postGainDb = postGain;
+    limiterConfigList.push_back(cfg);
+}
+
 /**
  * Test DynamicsProcessing Engine Configuration
  */
@@ -485,8 +545,8 @@
 };
 
 TEST_P(DynamicsProcessingTestEngineArchitecture, SetAndGetEngineArch) {
-    EXPECT_NO_FATAL_FAILURE(addEngineConfig(mCfg));
-    SetAndGetDynamicsProcessingParameters();
+    addEngineConfig(mCfg);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -527,7 +587,7 @@
   public:
     DynamicsProcessingTestInputGain()
         : DynamicsProcessingTestHelper(std::get<INPUT_GAIN_INSTANCE_NAME>(GetParam())),
-          mInputGain(std::get<INPUT_GAIN_PARAM>(GetParam())){};
+          mInputGain(std::get<INPUT_GAIN_PARAM>(GetParam())) {};
 
     void SetUp() override { SetUpDynamicsProcessingEffect(); }
 
@@ -537,8 +597,8 @@
 };
 
 TEST_P(DynamicsProcessingTestInputGain, SetAndGetInputGain) {
-    EXPECT_NO_FATAL_FAILURE(addInputGain(mInputGain));
-    SetAndGetDynamicsProcessingParameters();
+    addInputGain(mInputGain);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -559,46 +619,90 @@
         });
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestInputGain);
 
+class DynamicsProcessingInputGainDataTest
+    : public ::testing::TestWithParam<std::pair<std::shared_ptr<IFactory>, Descriptor>>,
+      public DynamicsProcessingTestHelper {
+  public:
+    DynamicsProcessingInputGainDataTest()
+        : DynamicsProcessingTestHelper((GetParam()), AudioChannelLayout::LAYOUT_MONO) {
+        mInput.resize(kFrameCount * mChannelCount);
+    }
+
+    void SetUp() override {
+        SetUpDynamicsProcessingEffect();
+        SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        ASSERT_NO_FATAL_FAILURE(generateSineWave(kInputFrequency /*Input Frequency*/, mInput, 1.0,
+                                                 kSamplingFrequency, mChannelLayout));
+        mInputDb = calculateDb(mInput);
+    }
+
+    void TearDown() override { TearDownDynamicsProcessingEffect(); }
+
+    void cleanUpInputGainConfig() {
+        CleanUp();
+        mInputGain.clear();
+    }
+
+    std::vector<DynamicsProcessing::InputGain> mInputGain;
+    std::vector<float> mInput;
+    float mInputDb;
+};
+
+TEST_P(DynamicsProcessingInputGainDataTest, SetAndGetInputGain) {
+    std::vector<float> gainDbValues = {-85, -40, 0, 40, 85};
+    for (float gainDb : gainDbValues) {
+        cleanUpInputGainConfig();
+        for (int i = 0; i < mChannelCount; i++) {
+            mInputGain.push_back(DynamicsProcessing::InputGain(i, gainDb));
+        }
+        std::vector<float> output(mInput.size());
+        addInputGain(mInputGain);
+        EXPECT_NO_FATAL_FAILURE(setParamsAndProcess(mInput, output));
+        if (!isAllParamsValid()) {
+            continue;
+        }
+        float outputDb = calculateDb(output, kStartIndex);
+        EXPECT_NEAR(outputDb, mInputDb + gainDb, kToleranceDb)
+                << "InputGain: " << gainDb << ", OutputDb: " << outputDb;
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingInputGainDataTest,
+                         testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+                                 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
+                         [](const auto& info) {
+                             auto descriptor = info.param;
+                             std::string name = getPrefix(descriptor.second);
+                             std::replace_if(
+                                     name.begin(), name.end(),
+                                     [](const char c) { return !std::isalnum(c); }, '_');
+                             return name;
+                         });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingInputGainDataTest);
+
 /**
  * Test DynamicsProcessing Limiter Config
  */
 enum LimiterConfigTestParamName {
     LIMITER_INSTANCE_NAME,
     LIMITER_CHANNEL,
-    LIMITER_ENABLE,
     LIMITER_LINK_GROUP,
-    LIMITER_ADDITIONAL,
-};
-enum LimiterConfigTestAdditionalParam {
     LIMITER_ATTACK_TIME,
     LIMITER_RELEASE_TIME,
     LIMITER_RATIO,
     LIMITER_THRESHOLD,
     LIMITER_POST_GAIN,
-    LIMITER_MAX_NUM,
 };
-using LimiterConfigTestAdditional = std::array<float, LIMITER_MAX_NUM>;
-// attackTime, releaseTime, ratio, thresh, postGain
-static constexpr std::array<LimiterConfigTestAdditional, 4> kLimiterConfigTestAdditionalParam = {
-        {{-1, -60, -2.5, -2, -3.14},
-         {-1, 60, -2.5, 2, -3.14},
-         {1, -60, 2.5, -2, 3.14},
-         {1, 60, 2.5, -2, 3.14}}};
 
 using LimiterConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>,
-                                           int32_t, bool, int32_t, LimiterConfigTestAdditional>;
+                                           int32_t, int32_t, float, float, float, float, float>;
 
-void fillLimiterConfig(DynamicsProcessing::LimiterConfig& cfg,
+void fillLimiterConfig(std::vector<DynamicsProcessing::LimiterConfig>& cfg,
                        const LimiterConfigTestParams& params) {
-    const std::array<float, LIMITER_MAX_NUM> additional = std::get<LIMITER_ADDITIONAL>(params);
-    cfg.channel = std::get<LIMITER_CHANNEL>(params);
-    cfg.enable = std::get<LIMITER_ENABLE>(params);
-    cfg.linkGroup = std::get<LIMITER_LINK_GROUP>(params);
-    cfg.attackTimeMs = additional[LIMITER_ATTACK_TIME];
-    cfg.releaseTimeMs = additional[LIMITER_RELEASE_TIME];
-    cfg.ratio = additional[LIMITER_RATIO];
-    cfg.thresholdDb = additional[LIMITER_THRESHOLD];
-    cfg.postGainDb = additional[LIMITER_POST_GAIN];
+    fillLimiterConfig(cfg, std::get<LIMITER_CHANNEL>(params), true,
+                      std::get<LIMITER_LINK_GROUP>(params), std::get<LIMITER_ATTACK_TIME>(params),
+                      std::get<LIMITER_RELEASE_TIME>(params), std::get<LIMITER_RATIO>(params),
+                      std::get<LIMITER_THRESHOLD>(params), std::get<LIMITER_POST_GAIN>(params));
 }
 
 class DynamicsProcessingTestLimiterConfig
@@ -607,7 +711,7 @@
   public:
     DynamicsProcessingTestLimiterConfig()
         : DynamicsProcessingTestHelper(std::get<LIMITER_INSTANCE_NAME>(GetParam())) {
-        fillLimiterConfig(mCfg, GetParam());
+        fillLimiterConfig(mLimiterConfigList, GetParam());
     }
 
     void SetUp() override { SetUpDynamicsProcessingEffect(); }
@@ -615,36 +719,203 @@
     void TearDown() override { TearDownDynamicsProcessingEffect(); }
 
     DynamicsProcessing::LimiterConfig mCfg;
+    std::vector<DynamicsProcessing::LimiterConfig> mLimiterConfigList;
 };
 
 TEST_P(DynamicsProcessingTestLimiterConfig, SetAndGetLimiterConfig) {
-    EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
-    EXPECT_NO_FATAL_FAILURE(addLimiterConfig({mCfg}));
-    SetAndGetDynamicsProcessingParameters();
+    addEngineConfig(mEngineConfigPreset);
+    addLimiterConfig(mLimiterConfigList);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
 }
 
 INSTANTIATE_TEST_SUITE_P(
         DynamicsProcessingTest, DynamicsProcessingTestLimiterConfig,
         ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
                                    IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
-                           testing::Values(-1, 0, 1, 2),                           // channel count
-                           testing::Bool(),                                        // enable
-                           testing::Values(3),                                     // link group
-                           testing::ValuesIn(kLimiterConfigTestAdditionalParam)),  // Additional
+                           testing::Values(-1, 0, 1, 2),  // channel index
+                           testing::Values(3),            // link group
+                           testing::Values(-1, 1),        // attackTime
+                           testing::Values(-60, 60),      // releaseTime
+                           testing::Values(-2.5, 2.5),    // ratio
+                           testing::Values(-2, 2),        // thresh
+                           testing::Values(-3.14, 3.14)   // postGain
+                           ),
         [](const auto& info) {
             auto descriptor = std::get<LIMITER_INSTANCE_NAME>(info.param).second;
-            DynamicsProcessing::LimiterConfig cfg;
+            std::vector<DynamicsProcessing::LimiterConfig> cfg;
             fillLimiterConfig(cfg, info.param);
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               toString(descriptor.common.id.uuid) + "_limiterConfig_" +
-                               cfg.toString();
+            std::string name =
+                    "Implementer_" + getPrefix(descriptor) + "_limiterConfig_" + cfg[0].toString();
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
         });
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingTestLimiterConfig);
 
+using LimiterConfigDataTestParams = std::pair<std::shared_ptr<IFactory>, Descriptor>;
+
+class DynamicsProcessingLimiterConfigDataTest
+    : public ::testing::TestWithParam<LimiterConfigDataTestParams>,
+      public DynamicsProcessingTestHelper {
+  public:
+    DynamicsProcessingLimiterConfigDataTest()
+        : DynamicsProcessingTestHelper(GetParam(), AudioChannelLayout::LAYOUT_MONO) {
+        mBufferSize = kFrameCount * mChannelCount;
+        mInput.resize(mBufferSize);
+    }
+
+    void SetUp() override {
+        SetUpDynamicsProcessingEffect();
+        SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        ASSERT_NO_FATAL_FAILURE(generateSineWave(1000 /*Input Frequency*/, mInput, 1.0,
+                                                 kSamplingFrequency, mChannelLayout));
+        mInputDb = calculateDb(mInput);
+    }
+
+    void TearDown() override { TearDownDynamicsProcessingEffect(); }
+
+    void computeThreshold(float ratio, float outputDb, float& threshold) {
+        EXPECT_NE(ratio, 0);
+        threshold = (mInputDb - (ratio * outputDb)) / (1 - ratio);
+    }
+
+    void computeRatio(float threshold, float outputDb, float& ratio) {
+        float inputOverThreshold = mInputDb - threshold;
+        float outputOverThreshold = outputDb - threshold;
+        EXPECT_NE(outputOverThreshold, 0);
+        ratio = inputOverThreshold / outputOverThreshold;
+    }
+
+    void setLimiterParamsAndProcess(std::vector<float>& input, std::vector<float>& output) {
+        addEngineConfig(mEngineConfigPreset);
+        addLimiterConfig(mLimiterConfigList);
+        EXPECT_NO_FATAL_FAILURE(setParamsAndProcess(input, output));
+    }
+
+    void cleanUpLimiterConfig() {
+        CleanUp();
+        mLimiterConfigList.clear();
+    }
+    static constexpr float kDefaultLinkerGroup = 3;
+    static constexpr float kDefaultAttackTime = 0;
+    static constexpr float kDefaultReleaseTime = 0;
+    static constexpr float kDefaultRatio = 4;
+    static constexpr float kDefaultThreshold = -10;
+    static constexpr float kDefaultPostGain = 0;
+    std::vector<DynamicsProcessing::LimiterConfig> mLimiterConfigList;
+    std::vector<float> mInput;
+    float mInputDb;
+    int mBufferSize;
+};
+
+TEST_P(DynamicsProcessingLimiterConfigDataTest, IncreasingThresholdDb) {
+    std::vector<float> thresholdValues = {-200, -150, -100, -50, -5, 0};
+    std::vector<float> output(mInput.size());
+    float previousThreshold = -FLT_MAX;
+    for (float threshold : thresholdValues) {
+        cleanUpLimiterConfig();
+        for (int i = 0; i < mChannelCount; i++) {
+            fillLimiterConfig(mLimiterConfigList, i, true, kDefaultLinkerGroup, kDefaultAttackTime,
+                              kDefaultReleaseTime, kDefaultRatio, threshold, kDefaultPostGain);
+        }
+        EXPECT_NO_FATAL_FAILURE(setLimiterParamsAndProcess(mInput, output));
+        if (!isAllParamsValid()) {
+            continue;
+        }
+        float outputDb = calculateDb(output, kStartIndex);
+        if (threshold >= mInputDb || kDefaultRatio == 1) {
+            EXPECT_NEAR(mInputDb, outputDb, kToleranceDb);
+        } else {
+            float calculatedThreshold = 0;
+            EXPECT_NO_FATAL_FAILURE(computeThreshold(kDefaultRatio, outputDb, calculatedThreshold));
+            ASSERT_GT(calculatedThreshold, previousThreshold);
+            previousThreshold = calculatedThreshold;
+        }
+    }
+}
+
+TEST_P(DynamicsProcessingLimiterConfigDataTest, IncreasingRatio) {
+    std::vector<float> ratioValues = {1, 10, 20, 30, 40, 50};
+    std::vector<float> output(mInput.size());
+    float previousRatio = 0;
+    for (float ratio : ratioValues) {
+        cleanUpLimiterConfig();
+        for (int i = 0; i < mChannelCount; i++) {
+            fillLimiterConfig(mLimiterConfigList, i, true, kDefaultLinkerGroup, kDefaultAttackTime,
+                              kDefaultReleaseTime, ratio, kDefaultThreshold, kDefaultPostGain);
+        }
+        EXPECT_NO_FATAL_FAILURE(setLimiterParamsAndProcess(mInput, output));
+        if (!isAllParamsValid()) {
+            continue;
+        }
+        float outputDb = calculateDb(output, kStartIndex);
+
+        if (kDefaultThreshold >= mInputDb) {
+            EXPECT_NEAR(mInputDb, outputDb, kToleranceDb);
+        } else {
+            float calculatedRatio = 0;
+            EXPECT_NO_FATAL_FAILURE(computeRatio(kDefaultThreshold, outputDb, calculatedRatio));
+            ASSERT_GT(calculatedRatio, previousRatio);
+            previousRatio = calculatedRatio;
+        }
+    }
+}
+
+TEST_P(DynamicsProcessingLimiterConfigDataTest, IncreasingPostGain) {
+    std::vector<float> postGainDbValues = {-85, -40, 0, 40, 85};
+    std::vector<float> output(mInput.size());
+    for (float postGainDb : postGainDbValues) {
+        cleanUpLimiterConfig();
+        for (int i = 0; i < mChannelCount; i++) {
+            fillLimiterConfig(mLimiterConfigList, i, true, kDefaultLinkerGroup, kDefaultAttackTime,
+                              kDefaultReleaseTime, kDefaultRatio, -1, postGainDb);
+        }
+        EXPECT_NO_FATAL_FAILURE(setLimiterParamsAndProcess(mInput, output));
+        if (!isAllParamsValid()) {
+            continue;
+        }
+        float outputDb = calculateDb(output, kStartIndex);
+        EXPECT_NEAR(outputDb, mInputDb + postGainDb, kToleranceDb)
+                << "PostGain: " << postGainDb << ", OutputDb: " << outputDb;
+    }
+}
+
+TEST_P(DynamicsProcessingLimiterConfigDataTest, LimiterEnableDisable) {
+    std::vector<bool> limiterEnableValues = {false, true};
+    std::vector<float> output(mInput.size());
+    for (bool isEnabled : limiterEnableValues) {
+        cleanUpLimiterConfig();
+        for (int i = 0; i < mChannelCount; i++) {
+            // Set non-default values
+            fillLimiterConfig(mLimiterConfigList, i, isEnabled, kDefaultLinkerGroup,
+                              5 /*attack time*/, 5 /*release time*/, 10 /*ratio*/,
+                              -10 /*threshold*/, 5 /*postgain*/);
+        }
+        EXPECT_NO_FATAL_FAILURE(setLimiterParamsAndProcess(mInput, output));
+        if (!isAllParamsValid()) {
+            continue;
+        }
+        if (isEnabled) {
+            EXPECT_NE(mInputDb, calculateDb(output, kStartIndex));
+        } else {
+            EXPECT_NEAR(mInputDb, calculateDb(output, kStartIndex), kToleranceDb);
+        }
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(DynamicsProcessingTest, DynamicsProcessingLimiterConfigDataTest,
+                         testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+                                 IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
+                         [](const auto& info) {
+                             auto descriptor = info.param;
+                             std::string name = getPrefix(descriptor.second);
+                             std::replace_if(
+                                     name.begin(), name.end(),
+                                     [](const char c) { return !std::isalnum(c); }, '_');
+                             return name;
+                         });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicsProcessingLimiterConfigDataTest);
+
 /**
  * Test DynamicsProcessing ChannelConfig
  */
@@ -671,21 +942,21 @@
 };
 
 TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPreEqChannelConfig) {
-    EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
-    EXPECT_NO_FATAL_FAILURE(addPreEqChannelConfig(mCfg));
-    SetAndGetDynamicsProcessingParameters();
+    addEngineConfig(mEngineConfigPreset);
+    addPreEqChannelConfig(mCfg);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
 }
 
 TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetPostEqChannelConfig) {
-    EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
-    EXPECT_NO_FATAL_FAILURE(addPostEqChannelConfig(mCfg));
-    SetAndGetDynamicsProcessingParameters();
+    addEngineConfig(mEngineConfigPreset);
+    addPostEqChannelConfig(mCfg);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
 }
 
 TEST_P(DynamicsProcessingTestChannelConfig, SetAndGetMbcChannelConfig) {
-    EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
-    EXPECT_NO_FATAL_FAILURE(addMbcChannelConfig(mCfg));
-    SetAndGetDynamicsProcessingParameters();
+    addEngineConfig(mEngineConfigPreset);
+    addMbcChannelConfig(mCfg);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -715,12 +986,11 @@
 enum EqBandConfigTestParamName {
     EQ_BAND_INSTANCE_NAME,
     EQ_BAND_CHANNEL,
-    EQ_BAND_ENABLE,
     EQ_BAND_CUT_OFF_FREQ,
     EQ_BAND_GAIN
 };
 using EqBandConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t,
-                                          bool, std::vector<std::pair<int, float>>, float>;
+                                          std::vector<std::pair<int, float>>, float>;
 
 void fillEqBandConfig(std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
                       const EqBandConfigTestParams& params) {
@@ -730,7 +1000,7 @@
     for (int i = 0; i < bandCount; i++) {
         cfgs[i].channel = std::get<EQ_BAND_CHANNEL>(params);
         cfgs[i].band = cutOffFreqs[i].first;
-        cfgs[i].enable = std::get<EQ_BAND_ENABLE>(params);
+        cfgs[i].enable = true /*Eqband Enable*/;
         cfgs[i].cutoffFrequencyHz = cutOffFreqs[i].second;
         cfgs[i].gainDb = std::get<EQ_BAND_GAIN>(params);
     }
@@ -753,28 +1023,28 @@
 
 TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPreEqBandConfig) {
     mEngineConfigPreset.preEqStage.bandCount = mCfgs.size();
-    EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
+    addEngineConfig(mEngineConfigPreset);
     std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
     for (int i = 0; i < mChannelCount; i++) {
         cfgs[i].channel = i;
         cfgs[i].enable = true;
     }
-    EXPECT_NO_FATAL_FAILURE(addPreEqChannelConfig(cfgs));
-    EXPECT_NO_FATAL_FAILURE(addPreEqBandConfigs(mCfgs));
-    SetAndGetDynamicsProcessingParameters();
+    addPreEqChannelConfig(cfgs);
+    addPreEqBandConfigs(mCfgs);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
 }
 
 TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPostEqBandConfig) {
     mEngineConfigPreset.postEqStage.bandCount = mCfgs.size();
-    EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
+    addEngineConfig(mEngineConfigPreset);
     std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
     for (int i = 0; i < mChannelCount; i++) {
         cfgs[i].channel = i;
         cfgs[i].enable = true;
     }
-    EXPECT_NO_FATAL_FAILURE(addPostEqChannelConfig(cfgs));
-    EXPECT_NO_FATAL_FAILURE(addPostEqBandConfigs(mCfgs));
-    SetAndGetDynamicsProcessingParameters();
+    addPostEqChannelConfig(cfgs);
+    addPostEqBandConfigs(mCfgs);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
 }
 
 std::vector<std::vector<std::pair<int, float>>> kBands{
@@ -825,9 +1095,8 @@
         DynamicsProcessingTest, DynamicsProcessingTestEqBandConfig,
         ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
                                    IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
-                           testing::Values(-1, 0, 10),     // channel ID
-                           testing::Bool(),                // band enable
-                           testing::ValuesIn(kBands),      // cut off frequencies
+                           testing::Values(-1, 0, 10),     // channel index
+                           testing::ValuesIn(kBands),      // band index, cut off frequencies
                            testing::Values(-3.14f, 3.14f)  // gain
                            ),
         [](const auto& info) {
@@ -851,7 +1120,6 @@
 enum MbcBandConfigParamName {
     MBC_BAND_INSTANCE_NAME,
     MBC_BAND_CHANNEL,
-    MBC_BAND_ENABLE,
     MBC_BAND_CUTOFF_FREQ,
     MBC_BAND_ADDITIONAL
 };
@@ -877,7 +1145,7 @@
          {3, 10, 2, -2, -5, 90, 2.5, 2, 2}}};
 
 using TestParamsMbcBandConfig =
-        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t, bool,
+        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t,
                    std::vector<std::pair<int, float>>, TestParamsMbcBandConfigAdditional>;
 
 void fillMbcBandConfig(std::vector<DynamicsProcessing::MbcBandConfig>& cfgs,
@@ -890,7 +1158,7 @@
         cfgs[i] = DynamicsProcessing::MbcBandConfig{
                 .channel = std::get<MBC_BAND_CHANNEL>(params),
                 .band = cutOffFreqs[i].first,
-                .enable = std::get<MBC_BAND_ENABLE>(params),
+                .enable = true /*Mbc Band Enable*/,
                 .cutoffFrequencyHz = cutOffFreqs[i].second,
                 .attackTimeMs = additional[MBC_ADD_ATTACK_TIME],
                 .releaseTimeMs = additional[MBC_ADD_RELEASE_TIME],
@@ -922,24 +1190,23 @@
 
 TEST_P(DynamicsProcessingTestMbcBandConfig, SetAndGetMbcBandConfig) {
     mEngineConfigPreset.mbcStage.bandCount = mCfgs.size();
-    EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
+    addEngineConfig(mEngineConfigPreset);
     std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
     for (int i = 0; i < mChannelCount; i++) {
         cfgs[i].channel = i;
         cfgs[i].enable = true;
     }
-    EXPECT_NO_FATAL_FAILURE(addMbcChannelConfig(cfgs));
-    EXPECT_NO_FATAL_FAILURE(addMbcBandConfigs(mCfgs));
-    SetAndGetDynamicsProcessingParameters();
+    addMbcChannelConfig(cfgs);
+    addMbcBandConfigs(mCfgs);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetDynamicsProcessingParameters());
 }
 
 INSTANTIATE_TEST_SUITE_P(
         DynamicsProcessingTest, DynamicsProcessingTestMbcBandConfig,
         ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
                                    IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
-                           testing::Values(-1, 0, 10),  // channel count
-                           testing::Bool(),             // enable
-                           testing::ValuesIn(kBands),   // cut off frequencies
+                           testing::Values(-1, 0, 10),  // channel index
+                           testing::ValuesIn(kBands),   // band index, cut off frequencies
                            testing::ValuesIn(kMbcBandConfigAdditionalParam)),  // Additional
         [](const auto& info) {
             auto descriptor = std::get<MBC_BAND_INSTANCE_NAME>(info.param).second;
diff --git a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
index e31aae6..0222923 100644
--- a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
@@ -43,13 +43,13 @@
 static const std::vector<TagVectorPair> kParamsIncreasingVector = {
         {EnvironmentalReverb::roomLevelMb, {-3500, -2800, -2100, -1400, -700, 0}},
         {EnvironmentalReverb::roomHfLevelMb, {-4000, -3200, -2400, -1600, -800, 0}},
-        {EnvironmentalReverb::decayTimeMs, {800, 1600, 2400, 3200, 4000}},
-        {EnvironmentalReverb::decayHfRatioPm, {100, 600, 1100, 1600, 2000}},
+        {EnvironmentalReverb::decayTimeMs, {400, 800, 1200, 1600, 2000}},
+        {EnvironmentalReverb::decayHfRatioPm, {1000, 900, 800, 700}},
         {EnvironmentalReverb::levelMb, {-3500, -2800, -2100, -1400, -700, 0}},
 };
 
 static const TagVectorPair kDiffusionParam = {EnvironmentalReverb::diffusionPm,
-                                              {200, 400, 600, 800, 1000}};
+                                              {100, 300, 500, 700, 900}};
 static const TagVectorPair kDensityParam = {EnvironmentalReverb::densityPm,
                                             {0, 200, 400, 600, 800, 1000}};
 
@@ -139,6 +139,7 @@
 
     return valueTag;
 }
+
 /**
  * Tests do the following:
  * - Testing parameter range supported by the effect. Range is verified with IEffect.getDescriptor()
@@ -224,13 +225,6 @@
                                                output.size());
     }
 
-    void generateSineWaveInput(std::vector<float>& input) {
-        int frequency = 1000;
-        size_t kSamplingFrequency = 44100;
-        for (size_t i = 0; i < input.size(); i++) {
-            input[i] = sin(2 * M_PI * frequency * i / kSamplingFrequency);
-        }
-    }
     using Maker = EnvironmentalReverb (*)(int);
 
     static constexpr std::array<Maker, static_cast<int>(EnvironmentalReverb::bypass) + 1>
@@ -286,13 +280,13 @@
         }
     }
 
-    static constexpr int kSamplingFrequency = 44100;
     static constexpr int kDurationMilliSec = 500;
     static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
+    static constexpr int kInputFrequency = 2000;
+    static constexpr int mChannelLayout = AudioChannelLayout::LAYOUT_STEREO;
 
-    int mStereoChannelCount =
-            getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
-                    AudioChannelLayout::LAYOUT_STEREO));
+    int mStereoChannelCount = getChannelCount(
+            AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout));
     int mFrameCount = kBufferSize / mStereoChannelCount;
 
     std::shared_ptr<IFactory> mFactory;
@@ -351,10 +345,11 @@
         : EnvironmentalReverbHelper(std::get<DESCRIPTOR_INDEX>(GetParam())) {
         std::tie(mTag, mParamValues) = std::get<TAG_VALUE_PAIR>(GetParam());
         mInput.resize(kBufferSize);
-        generateSineWaveInput(mInput);
     }
     void SetUp() override {
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        ASSERT_NO_FATAL_FAILURE(
+                generateSineWave(kInputFrequency, mInput, 1.0, kSamplingFrequency, mChannelLayout));
         SetUpReverb();
     }
     void TearDown() override {
@@ -441,7 +436,8 @@
 
 TEST_P(EnvironmentalReverbMinimumParamTest, MinimumValueTest) {
     std::vector<float> input(kBufferSize);
-    generateSineWaveInput(input);
+    ASSERT_NO_FATAL_FAILURE(
+            generateSineWave(kInputFrequency, input, 1.0, kSamplingFrequency, mChannelLayout));
     std::vector<float> output(kBufferSize);
     setParameterAndProcess(input, output, mValue, mTag);
     float energy = computeOutputEnergy(input, output);
@@ -477,10 +473,11 @@
         : EnvironmentalReverbHelper(std::get<DESCRIPTOR_INDEX>(GetParam())) {
         std::tie(mTag, mParamValues) = std::get<TAG_VALUE_PAIR>(GetParam());
         mInput.resize(kBufferSize);
-        generateSineWaveInput(mInput);
     }
     void SetUp() override {
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        ASSERT_NO_FATAL_FAILURE(
+                generateSineWave(kInputFrequency, mInput, 1.0, kSamplingFrequency, mChannelLayout));
         SetUpReverb();
     }
     void TearDown() override {
@@ -553,14 +550,15 @@
         mParamValues = std::get<PARAM_DENSITY_VALUE>(GetParam());
         mIsInputMute = (std::get<IS_INPUT_MUTE>(GetParam()));
         mInput.resize(kBufferSize);
-        if (mIsInputMute) {
-            std::fill(mInput.begin(), mInput.end(), 0);
-        } else {
-            generateSineWaveInput(mInput);
-        }
     }
     void SetUp() override {
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        if (mIsInputMute) {
+            std::fill(mInput.begin(), mInput.end(), 0);
+        } else {
+            ASSERT_NO_FATAL_FAILURE(generateSineWave(kInputFrequency, mInput, 1.0,
+                                                     kSamplingFrequency, mChannelLayout));
+        }
         SetUpReverb();
     }
     void TearDown() override {
diff --git a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
index 2b6dc3d..2802bf9 100644
--- a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
@@ -21,11 +21,13 @@
 #define LOG_TAG "VtsHalHapticGeneratorTargetTest"
 #include <android-base/logging.h>
 #include <android/binder_enums.h>
+#include <audio_utils/power.h>
 
 #include "EffectHelper.h"
 
 using namespace android;
 
+using aidl::android::hardware::audio::common::getChannelCount;
 using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator;
 using aidl::android::hardware::audio::effect::HapticGenerator;
@@ -34,406 +36,412 @@
 using aidl::android::hardware::audio::effect::Parameter;
 using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
-/**
- * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
- * VtsAudioEffectTargetTest.
- */
-enum ParamName {
-    PARAM_INSTANCE_NAME,
-    PARAM_HAPTIC_SCALE_ID,
-    PARAM_HAPTIC_SCALE_VIBRATOR_SCALE,
-    PARAM_VIBRATION_INFORMATION_RESONANT_FREQUENCY,
-    PARAM_VIBRATION_INFORMATION_Q_FACTOR,
-    PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE,
-};
-using HapticGeneratorParamTestParam =
-        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int,
-                   HapticGenerator::VibratorScale, float, float, float>;
-
-/*
- * Testing parameter range, assuming the parameter supported by effect is in this range.
- * Parameter should be within the valid range defined in the documentation,
- * for any supported value test expects EX_NONE from IEffect.setParameter(),
- * otherwise expect EX_ILLEGAL_ARGUMENT.
- */
-
-// TODO : Update the test values once range/capability is updated by implementation
 const int MIN_ID = std::numeric_limits<int>::min();
 const int MAX_ID = std::numeric_limits<int>::max();
 const float MIN_FLOAT = std::numeric_limits<float>::min();
 const float MAX_FLOAT = std::numeric_limits<float>::max();
 
-const std::vector<int> kHapticScaleIdValues = {MIN_ID, 0, MAX_ID};
-const std::vector<HapticGenerator::VibratorScale> kVibratorScaleValues = {
+std::vector<HapticGenerator::VibratorScale> kScaleValues = {
         ndk::enum_range<HapticGenerator::VibratorScale>().begin(),
         ndk::enum_range<HapticGenerator::VibratorScale>().end()};
 
+const std::vector<float> kScaleFactorValues = {HapticGenerator::HapticScale::UNDEFINED_SCALE_FACTOR,
+                                               0.0f, 0.5f, 1.0f, MAX_FLOAT};
+const std::vector<float> kAdaptiveScaleFactorValues = {
+        HapticGenerator::HapticScale::UNDEFINED_SCALE_FACTOR, 0.0f, 0.5f, 1.0f, MAX_FLOAT};
+
 const std::vector<float> kResonantFrequencyValues = {MIN_FLOAT, 100, MAX_FLOAT};
 const std::vector<float> kQFactorValues = {MIN_FLOAT, 100, MAX_FLOAT};
 const std::vector<float> kMaxAmplitude = {MIN_FLOAT, 100, MAX_FLOAT};
 
-class HapticGeneratorParamTest : public ::testing::TestWithParam<HapticGeneratorParamTestParam>,
-                                 public EffectHelper {
+constexpr int HAPTIC_SCALE_FACTORS_EFFECT_MIN_VERSION = 3;
+
+static const std::vector<int32_t> kHapticOutputLayouts = {
+        AudioChannelLayout::LAYOUT_MONO_HAPTIC_A, AudioChannelLayout::LAYOUT_MONO_HAPTIC_AB,
+        AudioChannelLayout::LAYOUT_STEREO_HAPTIC_A, AudioChannelLayout::LAYOUT_STEREO_HAPTIC_AB};
+
+class HapticGeneratorHelper : public EffectHelper {
   public:
-    HapticGeneratorParamTest()
-        : mParamHapticScaleId(std::get<PARAM_HAPTIC_SCALE_ID>(GetParam())),
-          mParamVibratorScale(std::get<PARAM_HAPTIC_SCALE_VIBRATOR_SCALE>(GetParam())),
-          mParamResonantFrequency(
-                  std::get<PARAM_VIBRATION_INFORMATION_RESONANT_FREQUENCY>(GetParam())),
-          mParamQFactor(std::get<PARAM_VIBRATION_INFORMATION_Q_FACTOR>(GetParam())),
-          mParamMaxAmplitude(std::get<PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE>(GetParam())) {
-        std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
-    }
-    void SetUp() override {
+    void SetUpHapticGenerator(int32_t chMask = AudioChannelLayout::CHANNEL_HAPTIC_A) {
         ASSERT_NE(nullptr, mFactory);
         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+        EXPECT_STATUS(EX_NONE, mEffect->getInterfaceVersion(&mEffectInterfaceVersion));
+
+        AudioChannelLayout layout =
+                AudioChannelLayout::make<AudioChannelLayout::layoutMask>(chMask);
 
         Parameter::Common common = createParamCommon(
-                0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
-                kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
-        IEffect::OpenEffectReturn ret;
+                0 /* session */, 1 /* ioHandle */, kSamplingFrequency /* iSampleRate */,
+                kSamplingFrequency /* oSampleRate */, kFrameCount /* iFrameCount */,
+                kFrameCount /* oFrameCount */, layout, layout);
         ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt, &ret, EX_NONE));
         ASSERT_NE(nullptr, mEffect);
     }
 
-    void TearDown() override {
+    void TearDownHapticGenerator() {
         ASSERT_NO_FATAL_FAILURE(close(mEffect));
         ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+        ret = IEffect::OpenEffectReturn{};
     }
 
-    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+    Parameter createScaleParam(const std::vector<HapticGenerator::HapticScale>& hapticScales) {
+        return Parameter::make<Parameter::specific>(
+                Parameter::Specific::make<Parameter::Specific::hapticGenerator>(
+                        HapticGenerator::make<HapticGenerator::hapticScales>(hapticScales)));
+    }
+
+    Parameter createVibratorParam(HapticGenerator::VibratorInformation vibrationInfo) {
+        return Parameter::make<Parameter::specific>(
+                Parameter::Specific::make<Parameter::Specific::hapticGenerator>(
+                        HapticGenerator::make<HapticGenerator::vibratorInfo>(vibrationInfo)));
+    }
+
+    void setAndVerifyParameter(Parameter hapticParameter, HapticGenerator::Tag tag,
+                               binder_exception_t expected = EX_NONE) {
+        EXPECT_STATUS(expected, mEffect->setParameter(hapticParameter))
+                << hapticParameter.toString();
+        if (expected == EX_NONE) {
+            // get parameter
+            Parameter getParam;
+            auto second = Parameter::Id::make<Parameter::Id::hapticGeneratorTag>(
+                    HapticGenerator::Id::make<HapticGenerator::Id::commonTag>(
+                            HapticGenerator::Tag(tag)));
+            // If the set is successful, get param should match
+            EXPECT_STATUS(expected, mEffect->getParameter(second, &getParam));
+            EXPECT_EQ(hapticParameter, getParam) << "\nexpectedParam:" << hapticParameter.toString()
+                                                 << "\ngetParam:" << getParam.toString();
+        }
+    }
+
+    HapticGenerator::VibratorInformation createVibratorInfo(float resonantFrequency, float qFactor,
+                                                            float amplitude) {
+        return HapticGenerator::VibratorInformation(resonantFrequency, qFactor, amplitude);
+    }
+
+    static const long kFrameCount = 10000;
+    static constexpr int kSamplingFrequency = 44100;
+    static constexpr int kDefaultScaleID = 0;
+    static constexpr float kDefaultMaxAmp = 1;
+    static constexpr float kDefaultResonantFrequency = 150;
+    static constexpr float kDefaultQfactor = 8;
+    static constexpr HapticGenerator::VibratorScale kDefaultScale =
+            HapticGenerator::VibratorScale::NONE;
     std::shared_ptr<IFactory> mFactory;
     std::shared_ptr<IEffect> mEffect;
-    Descriptor mDescriptor;
-    int mParamHapticScaleId = 0;
-    HapticGenerator::VibratorScale mParamVibratorScale = HapticGenerator::VibratorScale::MUTE;
-    float mParamResonantFrequency = 0;
-    float mParamQFactor = 0;
-    float mParamMaxAmplitude = 0;
+    IEffect::OpenEffectReturn ret;
+    Parameter mHapticSpecificParameter;
+    Parameter::Id mHapticIdParameter;
+    int mEffectInterfaceVersion;
+};
 
-    void SetAndGetHapticGeneratorParameters() {
-        for (auto& it : mTags) {
-            auto& tag = std::get<ParamTestEnum::PARAM_TEST_TAG>(it);
-            auto& setHg = std::get<ParamTestEnum::PARAM_TEST_TARGET>(it);
+/**
+ *Tests do the following:
+ * -Testing parameter range supported by the effect.
+ * -For any supported value test expects EX_NONE from IEffect.setParameter(),
+ *  otherwise expect EX_ILLEGAL_ARGUMENT.
+ * -Validating the effect by comparing the output energies of the supported parameters.
+ **/
 
-            // set parameter
-            Parameter expectParam;
-            Parameter::Specific specific;
-            specific.set<Parameter::Specific::hapticGenerator>(setHg);
-            expectParam.set<Parameter::specific>(specific);
+using EffectInstance = std::pair<std::shared_ptr<IFactory>, Descriptor>;
 
-            const bool valid =
-                    isParameterValid<HapticGenerator, Range::hapticGenerator>(setHg, mDescriptor);
-            const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
-            EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString();
+class HapticGeneratorScaleParamTest : public ::testing::TestWithParam<EffectInstance>,
+                                      public HapticGeneratorHelper {
+  public:
+    HapticGeneratorScaleParamTest() { std::tie(mFactory, mDescriptor) = GetParam(); }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpHapticGenerator()); }
+    void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownHapticGenerator()); }
+};
 
-            // only get if parameter in range and set success
-            if (expected == EX_NONE) {
-                Parameter getParam;
-                Parameter::Id id;
-                HapticGenerator::Id hgId;
-                hgId.set<HapticGenerator::Id::commonTag>(tag);
-                id.set<Parameter::Id::hapticGeneratorTag>(hgId);
-                EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
-                EXPECT_EQ(expectParam, getParam) << expectParam.toString() << "\n"
-                                                 << getParam.toString();
+TEST_P(HapticGeneratorScaleParamTest, SetAndGetScales) {
+    std::vector<HapticGenerator::HapticScale> hapticScales;
+    for (int i = 0; i < static_cast<int>(kScaleValues.size()); i++) {
+        hapticScales.push_back({.id = i, .scale = kScaleValues[i]});
+    }
+    ASSERT_NO_FATAL_FAILURE(
+            setAndVerifyParameter(createScaleParam(hapticScales), HapticGenerator::hapticScales));
+}
+
+TEST_P(HapticGeneratorScaleParamTest, SetAndGetScaleFactors) {
+    if (mEffectInterfaceVersion < HAPTIC_SCALE_FACTORS_EFFECT_MIN_VERSION) {
+        GTEST_SKIP() << "Skipping HapticGenerator ScaleFactors test for effect version "
+                     << std::to_string(mEffectInterfaceVersion);
+    }
+
+    std::vector<HapticGenerator::HapticScale> hapticScales;
+    for (int i = 0; i < static_cast<int>(kScaleFactorValues.size()); i++) {
+        hapticScales.push_back(
+                {.id = i, .scale = kScaleValues[0], .scaleFactor = kScaleFactorValues[i]});
+    }
+    ASSERT_NO_FATAL_FAILURE(
+            setAndVerifyParameter(createScaleParam(hapticScales), HapticGenerator::hapticScales));
+}
+
+TEST_P(HapticGeneratorScaleParamTest, SetAndGetAdaptiveScaleFactors) {
+    if (mEffectInterfaceVersion < HAPTIC_SCALE_FACTORS_EFFECT_MIN_VERSION) {
+        GTEST_SKIP() << "Skipping HapticGenerator AdaptiveScaleFactors test for effect version "
+                     << std::to_string(mEffectInterfaceVersion);
+    }
+
+    std::vector<HapticGenerator::HapticScale> hapticScales;
+    for (int i = 0; i < static_cast<int>(kAdaptiveScaleFactorValues.size()); i++) {
+        hapticScales.push_back({.id = i,
+                                .scale = kScaleValues[0],
+                                .scaleFactor = kScaleFactorValues[3],
+                                .adaptiveScaleFactor = kAdaptiveScaleFactorValues[i]});
+    }
+    ASSERT_NO_FATAL_FAILURE(
+            setAndVerifyParameter(createScaleParam(hapticScales), HapticGenerator::hapticScales));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        HapticGeneratorValidTest, HapticGeneratorScaleParamTest,
+        testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+                IFactory::descriptor, getEffectTypeUuidHapticGenerator())),
+        [](const testing::TestParamInfo<HapticGeneratorScaleParamTest::ParamType>& info) {
+            auto descriptor = info.param;
+            return getPrefix(descriptor.second);
+        });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorScaleParamTest);
+
+enum VibratorParamName {
+    VIBRATOR_PARAM_INSTANCE,
+    VIBRATOR_PARAM_RESONANT_FREQUENCY,
+    VIBRATOR_PARAM_Q_FACTOR,
+    VIBRATOR_PARAM_MAX_AMPLITUDE,
+};
+
+using HapticGeneratorVibratorInfoTestParam = std::tuple<EffectInstance, float, float, float>;
+
+class HapticGeneratorVibratorInfoParamTest
+    : public ::testing::TestWithParam<HapticGeneratorVibratorInfoTestParam>,
+      public HapticGeneratorHelper {
+  public:
+    HapticGeneratorVibratorInfoParamTest()
+        : mParamResonantFrequency(std::get<VIBRATOR_PARAM_RESONANT_FREQUENCY>(GetParam())),
+          mParamQFactor(std::get<VIBRATOR_PARAM_Q_FACTOR>(GetParam())),
+          mParamMaxAmplitude(std::get<VIBRATOR_PARAM_MAX_AMPLITUDE>(GetParam())) {
+        std::tie(mFactory, mDescriptor) = std::get<VIBRATOR_PARAM_INSTANCE>(GetParam());
+    }
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpHapticGenerator()); }
+    void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownHapticGenerator()); }
+
+    float mParamResonantFrequency = kDefaultResonantFrequency;
+    float mParamQFactor = kDefaultQfactor;
+    float mParamMaxAmplitude = kDefaultMaxAmp;
+};
+
+TEST_P(HapticGeneratorVibratorInfoParamTest, SetAndGetVibratorInformation) {
+    auto vibratorInfo =
+            createVibratorInfo(mParamResonantFrequency, mParamQFactor, mParamMaxAmplitude);
+    if (isParameterValid<HapticGenerator, Range::hapticGenerator>(vibratorInfo, mDescriptor)) {
+        ASSERT_NO_FATAL_FAILURE(setAndVerifyParameter(createVibratorParam(vibratorInfo),
+                                                      HapticGenerator::vibratorInfo));
+    } else {
+        ASSERT_NO_FATAL_FAILURE(setAndVerifyParameter(createVibratorParam(vibratorInfo),
+                                                      HapticGenerator::vibratorInfo,
+                                                      EX_ILLEGAL_ARGUMENT));
+    }
+}
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorVibratorInfoParamTest);
+
+INSTANTIATE_TEST_SUITE_P(
+        HapticGeneratorValidTest, HapticGeneratorVibratorInfoParamTest,
+        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+                                   IFactory::descriptor, getEffectTypeUuidHapticGenerator())),
+                           testing::ValuesIn(kResonantFrequencyValues),
+                           testing::ValuesIn(kQFactorValues), testing::ValuesIn(kMaxAmplitude)),
+        [](const testing::TestParamInfo<HapticGeneratorVibratorInfoParamTest::ParamType>& info) {
+            auto descriptor = std::get<VIBRATOR_PARAM_INSTANCE>(info.param).second;
+            std::string resonantFrequency =
+                    std::to_string(std::get<VIBRATOR_PARAM_RESONANT_FREQUENCY>(info.param));
+            std::string qFactor = std::to_string(std::get<VIBRATOR_PARAM_Q_FACTOR>(info.param));
+            std::string maxAmplitude =
+                    std::to_string(std::get<VIBRATOR_PARAM_MAX_AMPLITUDE>(info.param));
+            std::string name = getPrefix(descriptor) + "_resonantFrequency" + resonantFrequency +
+                               "_qFactor" + qFactor + "_maxAmplitude" + maxAmplitude;
+            std::replace_if(
+                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+            return name;
+        });
+
+/**
+ * The data tests do the following
+ * -Generate test input.
+ * -Check if the parameters are supported. Skip the unsupported parameter values.
+ * -Validate increase in haptic output energy energy.
+ **/
+
+enum DataTestParam { EFFECT_INSTANCE, LAYOUT };
+using HapticGeneratorDataTestParam = std::tuple<EffectInstance, int32_t>;
+
+class HapticGeneratorDataTest : public ::testing::TestWithParam<HapticGeneratorDataTestParam>,
+                                public HapticGeneratorHelper {
+  public:
+    HapticGeneratorDataTest() : mChMask(std::get<LAYOUT>(GetParam())) {
+        std::tie(mFactory, mDescriptor) = std::get<EFFECT_INSTANCE>(GetParam());
+        mAudioChannelCount =
+                getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChMask),
+                                ~AudioChannelLayout::LAYOUT_HAPTIC_AB);
+        mHapticChannelCount =
+                getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChMask),
+                                AudioChannelLayout::LAYOUT_HAPTIC_AB);
+
+        mAudioSamples = kFrameCount * mAudioChannelCount;
+        mHapticSamples = kFrameCount * mHapticChannelCount;
+        mInput.resize(mHapticSamples + mAudioSamples, 0);
+        mOutput.resize(mHapticSamples + mAudioSamples, 0);
+    }
+
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpHapticGenerator(mChMask)); }
+    void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownHapticGenerator()); }
+
+    void generateSinePeriod() {
+        size_t cycleSize = kSamplingFrequency / kInputFrequency;
+        size_t startSize = 0;
+        while (startSize < mAudioSamples) {
+            for (size_t i = 0; i < cycleSize; i++) {
+                mInput[i + startSize] = sin(2 * M_PI * kInputFrequency * i / kSamplingFrequency);
+            }
+            startSize += mAudioSamples / 4;
+        }
+    }
+
+    void setBaseVibratorParam() {
+        auto vibratorInfo =
+                createVibratorInfo(kDefaultResonantFrequency, kDefaultQfactor, kDefaultMaxAmp);
+        if (isParameterValid<HapticGenerator, Range::hapticGenerator>(vibratorInfo, mDescriptor)) {
+            ASSERT_NO_FATAL_FAILURE(setAndVerifyParameter(createVibratorParam(vibratorInfo),
+                                                          HapticGenerator::vibratorInfo));
+        } else {
+            GTEST_SKIP() << "Invalid base vibrator values, skipping the test\n";
+        }
+    }
+
+    void setBaseScaleParam() {
+        ASSERT_NO_FATAL_FAILURE(setAndVerifyParameter(
+                createScaleParam({HapticGenerator::HapticScale(kDefaultScaleID, kDefaultScale)}),
+                HapticGenerator::hapticScales));
+    }
+
+    void validateIncreasingEnergy(HapticGenerator::Tag tag) {
+        float baseEnergy = -1;
+        for (auto param : mHapticParam) {
+            ASSERT_NO_FATAL_FAILURE(setAndVerifyParameter(param, tag));
+            SCOPED_TRACE("Param: " + param.toString());
+            ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput(mInput, mOutput, mEffect, &ret));
+            float hapticOutputEnergy = audio_utils_compute_energy_mono(
+                    mOutput.data() + mAudioSamples, AUDIO_FORMAT_PCM_FLOAT, mHapticSamples);
+            EXPECT_GT(hapticOutputEnergy, baseEnergy);
+            baseEnergy = hapticOutputEnergy;
+        }
+    }
+
+    float findAbsMax(auto begin, auto end) {
+        return *std::max_element(begin, end,
+                                 [](float a, float b) { return std::abs(a) < std::abs(b); });
+    }
+
+    void findMaxAmplitude() {
+        for (float amp = 0.1; amp <= 1; amp += 0.1) {
+            auto vibratorInfo = createVibratorInfo(kDefaultResonantFrequency, kDefaultQfactor, amp);
+            if (!isParameterValid<HapticGenerator, Range::hapticGenerator>(vibratorInfo,
+                                                                           mDescriptor)) {
+                continue;
+            }
+            ASSERT_NO_FATAL_FAILURE(setAndVerifyParameter(createVibratorParam(vibratorInfo),
+                                                          HapticGenerator::vibratorInfo));
+            ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput(mInput, mOutput, mEffect, &ret));
+            float outAmplitude = findAbsMax(mOutput.begin() + mAudioSamples, mOutput.end());
+            if (outAmplitude > mMaxAmplitude) {
+                mMaxAmplitude = outAmplitude;
+            } else {
+                break;
             }
         }
     }
 
-    void addHapticScaleParam(int id, HapticGenerator::VibratorScale scale) {
-        HapticGenerator setHg;
-        std::vector<HapticGenerator::HapticScale> hapticScales = {{.id = id, .scale = scale}};
-        setHg.set<HapticGenerator::hapticScales>(hapticScales);
-        mTags.push_back({HapticGenerator::hapticScales, setHg});
-    }
-
-    void addVibratorInformationParam(float resonantFrequencyHz, float qFactor, float maxAmplitude) {
-        HapticGenerator hg;
-        HapticGenerator::VibratorInformation vibrationInfo = {
-                .resonantFrequencyHz = resonantFrequencyHz,
-                .qFactor = qFactor,
-                .maxAmplitude = maxAmplitude};
-        hg.set<HapticGenerator::vibratorInfo>(vibrationInfo);
-        mTags.push_back({HapticGenerator::vibratorInfo, hg});
-    }
-
-  private:
-    enum ParamTestEnum { PARAM_TEST_TAG, PARAM_TEST_TARGET };
-    std::vector<std::tuple<HapticGenerator::Tag, HapticGenerator>> mTags;
-
-    void CleanUp() { mTags.clear(); }
+    const int kInputFrequency = 1000;
+    float mMaxAmplitude = 0;
+    size_t mHapticSamples;
+    int32_t mChMask;
+    int32_t mAudioChannelCount;
+    int32_t mHapticChannelCount;
+    size_t mAudioSamples;
+    float mBaseHapticOutputEnergy;
+    std::vector<Parameter> mHapticParam;
+    // both input and output buffer includes audio and haptic samples
+    std::vector<float> mInput;
+    std::vector<float> mOutput;
 };
 
-TEST_P(HapticGeneratorParamTest, SetAndGetHapticScale) {
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(mParamHapticScaleId, mParamVibratorScale));
-    SetAndGetHapticGeneratorParameters();
+TEST_P(HapticGeneratorDataTest, IncreasingVibratorScaleTest) {
+    generateInput(mInput, kInputFrequency, kSamplingFrequency, mAudioSamples);
+    ASSERT_NO_FATAL_FAILURE(setBaseVibratorParam());
+    for (HapticGenerator::VibratorScale scale : kScaleValues) {
+        mHapticParam.push_back(
+                createScaleParam({HapticGenerator::HapticScale(kDefaultScaleID, scale)}));
+    }
+    ASSERT_NO_FATAL_FAILURE(validateIncreasingEnergy(HapticGenerator::hapticScales));
 }
 
-TEST_P(HapticGeneratorParamTest, SetAndGetMultipleHapticScales) {
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(mParamHapticScaleId, mParamVibratorScale));
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(mParamHapticScaleId, mParamVibratorScale));
-    SetAndGetHapticGeneratorParameters();
+TEST_P(HapticGeneratorDataTest, IncreasingMaxAmplitudeTest) {
+    generateInput(mInput, kInputFrequency, kSamplingFrequency, mAudioSamples);
+    ASSERT_NO_FATAL_FAILURE(setBaseScaleParam());
+    findMaxAmplitude();
+    std::vector<float> increasingAmplitudeValues = {0.25f * mMaxAmplitude, 0.5f * mMaxAmplitude,
+                                                    0.75f * mMaxAmplitude, mMaxAmplitude};
+    for (float amplitude : increasingAmplitudeValues) {
+        auto vibratorInfo =
+                createVibratorInfo(kDefaultResonantFrequency, kDefaultQfactor, amplitude);
+        if (!isParameterValid<HapticGenerator, Range::hapticGenerator>(vibratorInfo, mDescriptor)) {
+            continue;
+        }
+        mHapticParam.push_back(createVibratorParam(vibratorInfo));
+    }
+    ASSERT_NO_FATAL_FAILURE(validateIncreasingEnergy(HapticGenerator::vibratorInfo));
 }
 
-TEST_P(HapticGeneratorParamTest, SetAndGetVibratorInformation) {
-    EXPECT_NO_FATAL_FAILURE(addVibratorInformationParam(mParamResonantFrequency, mParamQFactor,
-                                                        mParamMaxAmplitude));
-    SetAndGetHapticGeneratorParameters();
+TEST_P(HapticGeneratorDataTest, DescreasingResonantFrequencyTest) {
+    std::vector<float> descreasingResonantFrequency = {800, 600, 400, 200};
+    generateInput(mInput, kInputFrequency, kSamplingFrequency, mAudioSamples);
+    ASSERT_NO_FATAL_FAILURE(setBaseScaleParam());
+    for (float resonantFrequency : descreasingResonantFrequency) {
+        auto vibratorInfo = createVibratorInfo(resonantFrequency, kDefaultQfactor, kDefaultMaxAmp);
+        if (!isParameterValid<HapticGenerator, Range::hapticGenerator>(vibratorInfo, mDescriptor)) {
+            continue;
+        }
+        mHapticParam.push_back(createVibratorParam(vibratorInfo));
+    }
+    ASSERT_NO_FATAL_FAILURE(validateIncreasingEnergy(HapticGenerator::vibratorInfo));
+}
+
+TEST_P(HapticGeneratorDataTest, IncreasingQfactorTest) {
+    std::vector<float> increasingQfactor = {16, 24, 32, 40};
+    generateSinePeriod();
+    ASSERT_NO_FATAL_FAILURE(setBaseScaleParam());
+    for (float qFactor : increasingQfactor) {
+        auto vibratorInfo = createVibratorInfo(kDefaultResonantFrequency, qFactor, kDefaultMaxAmp);
+        if (!isParameterValid<HapticGenerator, Range::hapticGenerator>(vibratorInfo, mDescriptor)) {
+            continue;
+        }
+        mHapticParam.push_back(createVibratorParam(vibratorInfo));
+    }
+    ASSERT_NO_FATAL_FAILURE(validateIncreasingEnergy(HapticGenerator::vibratorInfo));
 }
 
 INSTANTIATE_TEST_SUITE_P(
-        HapticGeneratorValidTest, HapticGeneratorParamTest,
+        DataTest, HapticGeneratorDataTest,
         ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
                                    IFactory::descriptor, getEffectTypeUuidHapticGenerator())),
-                           testing::ValuesIn(kHapticScaleIdValues),
-                           testing::ValuesIn(kVibratorScaleValues),
-                           testing::ValuesIn(kResonantFrequencyValues),
-                           testing::ValuesIn(kQFactorValues), testing::ValuesIn(kMaxAmplitude)),
-        [](const testing::TestParamInfo<HapticGeneratorParamTest::ParamType>& info) {
-            auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
-            std::string hapticScaleID = std::to_string(std::get<PARAM_HAPTIC_SCALE_ID>(info.param));
-            std::string hapticScaleVibScale = std::to_string(
-                    static_cast<int>(std::get<PARAM_HAPTIC_SCALE_VIBRATOR_SCALE>(info.param)));
-            std::string resonantFrequency = std::to_string(
-                    std::get<PARAM_VIBRATION_INFORMATION_RESONANT_FREQUENCY>(info.param));
-            std::string qFactor =
-                    std::to_string(std::get<PARAM_VIBRATION_INFORMATION_Q_FACTOR>(info.param));
-            std::string maxAmplitude =
-                    std::to_string(std::get<PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE>(info.param));
-            std::string name = getPrefix(descriptor) + "_hapticScaleId" + hapticScaleID +
-                               "_hapticScaleVibScale" + hapticScaleVibScale + "_resonantFrequency" +
-                               resonantFrequency + "_qFactor" + qFactor + "_maxAmplitude" +
-                               maxAmplitude;
-            std::replace_if(
-                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+                           testing::ValuesIn(kHapticOutputLayouts)),
+        [](const testing::TestParamInfo<HapticGeneratorDataTest::ParamType>& info) {
+            auto descriptor = std::get<EFFECT_INSTANCE>(info.param).second;
+            std::string layout = "0x" + std::format("{:x}", std::get<LAYOUT>(info.param));
+            std::string name = getPrefix(descriptor) + "_layout_" + layout;
             return name;
         });
-
-INSTANTIATE_TEST_SUITE_P(
-        HapticGeneratorInvalidTest, HapticGeneratorParamTest,
-        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                                   IFactory::descriptor, getEffectTypeUuidHapticGenerator())),
-                           testing::Values(MIN_ID),
-                           testing::Values(HapticGenerator::VibratorScale::NONE),
-                           testing::Values(MIN_FLOAT), testing::Values(MIN_FLOAT),
-                           testing::Values(MIN_FLOAT)),
-        [](const testing::TestParamInfo<HapticGeneratorParamTest::ParamType>& info) {
-            auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
-            std::string hapticScaleID = std::to_string(std::get<PARAM_HAPTIC_SCALE_ID>(info.param));
-            std::string hapticScaleVibScale = std::to_string(
-                    static_cast<int>(std::get<PARAM_HAPTIC_SCALE_VIBRATOR_SCALE>(info.param)));
-            std::string resonantFrequency = std::to_string(
-                    std::get<PARAM_VIBRATION_INFORMATION_RESONANT_FREQUENCY>(info.param));
-            std::string qFactor =
-                    std::to_string(std::get<PARAM_VIBRATION_INFORMATION_Q_FACTOR>(info.param));
-            std::string maxAmplitude =
-                    std::to_string(std::get<PARAM_VIBRATION_INFORMATION_MAX_AMPLITUDE>(info.param));
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               toString(descriptor.common.id.uuid) + "_hapticScaleId" +
-                               hapticScaleID + "_hapticScaleVibScale" + hapticScaleVibScale +
-                               "_resonantFrequency" + resonantFrequency + "_qFactor" + qFactor +
-                               "_maxAmplitude" + maxAmplitude;
-            std::replace_if(
-                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
-            return name;
-        });
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorParamTest);
-
-// Test HapticScale[] hapticScales parameter
-using HapticGeneratorScalesTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>>;
-class HapticGeneratorScalesTest : public ::testing::TestWithParam<HapticGeneratorScalesTestParam>,
-                                  public EffectHelper {
-  public:
-    HapticGeneratorScalesTest() {
-        std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
-    }
-
-    void SetUp() override {
-        ASSERT_NE(nullptr, mFactory);
-        ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
-
-        Parameter::Common common = createParamCommon(
-                0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
-                kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
-        IEffect::OpenEffectReturn ret;
-        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt, &ret, EX_NONE));
-        ASSERT_NE(nullptr, mEffect);
-    }
-
-    void TearDown() override {
-        ASSERT_NO_FATAL_FAILURE(close(mEffect));
-        ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
-        CleanUp();
-    }
-
-    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
-    std::shared_ptr<IFactory> mFactory;
-    std::shared_ptr<IEffect> mEffect;
-    Descriptor mDescriptor;
-
-    void addHapticScaleParam(std::vector<HapticGenerator::HapticScale> scales) {
-        mHapticScales.push_back(HapticGenerator::make<HapticGenerator::hapticScales>(scales));
-        for (const auto& scale : scales) {
-            expectMap.insert_or_assign(scale.id, scale.scale);
-        }
-    }
-
-    void SetHapticScaleParameters() {
-        // std::unordered_set<HapticGenerator::HapticScale> target;
-        for (auto& it : mHapticScales) {
-            Parameter::Specific specific =
-                    Parameter::Specific::make<Parameter::Specific::hapticGenerator>(it);
-            Parameter param = Parameter::make<Parameter::specific>(specific);
-            EXPECT_STATUS(EX_NONE, mEffect->setParameter(param)) << param.toString();
-        }
-    }
-
-    void checkHapticScaleParameter() {
-        // get parameter
-        Parameter targetParam;
-        HapticGenerator::Id hgId = HapticGenerator::Id::make<HapticGenerator::Id::commonTag>(
-                HapticGenerator::hapticScales);
-        Parameter::Id id = Parameter::Id::make<Parameter::Id::hapticGeneratorTag>(hgId);
-        EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &targetParam));
-        ASSERT_EQ(Parameter::specific, targetParam.getTag());
-        Parameter::Specific specific = targetParam.get<Parameter::specific>();
-        ASSERT_EQ(Parameter::Specific::hapticGenerator, specific.getTag());
-        HapticGenerator hg = specific.get<Parameter::Specific::hapticGenerator>();
-        ASSERT_EQ(HapticGenerator::hapticScales, hg.getTag());
-        std::vector<HapticGenerator::HapticScale> scales = hg.get<HapticGenerator::hapticScales>();
-        ASSERT_EQ(scales.size(), expectMap.size());
-        for (const auto& scale : scales) {
-            auto itor = expectMap.find(scale.id);
-            ASSERT_NE(expectMap.end(), itor);
-            ASSERT_EQ(scale.scale, itor->second);
-            expectMap.erase(scale.id);
-        }
-        ASSERT_EQ(0ul, expectMap.size());
-    }
-
-    const static HapticGenerator::HapticScale kHapticScaleWithMinId;
-    const static HapticGenerator::HapticScale kHapticScaleWithMinIdNew;
-    const static HapticGenerator::HapticScale kHapticScale;
-    const static HapticGenerator::HapticScale kHapticScaleNew;
-    const static HapticGenerator::HapticScale kHapticScaleWithMaxId;
-    const static HapticGenerator::HapticScale kHapticScaleWithMaxIdNew;
-
-    std::vector<HapticGenerator> mHapticScales;
-
-    void CleanUp() {
-        mHapticScales.clear();
-        expectMap.clear();
-    }
-
-  private:
-    std::map<int /* trackID */, HapticGenerator::VibratorScale> expectMap;
-};
-
-const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleWithMinId = {
-        .id = MIN_ID, .scale = HapticGenerator::VibratorScale::MUTE};
-const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleWithMinIdNew = {
-        .id = MIN_ID, .scale = HapticGenerator::VibratorScale::VERY_LOW};
-const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScale = {
-        .id = 1, .scale = HapticGenerator::VibratorScale::LOW};
-const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleNew = {
-        .id = 1, .scale = HapticGenerator::VibratorScale::NONE};
-const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleWithMaxId = {
-        .id = MAX_ID, .scale = HapticGenerator::VibratorScale::VERY_HIGH};
-const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleWithMaxIdNew = {
-        .id = MAX_ID, .scale = HapticGenerator::VibratorScale::MUTE};
-
-TEST_P(HapticGeneratorScalesTest, SetAndUpdateOne) {
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScale}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleNew}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMinId}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMinIdNew}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMaxId}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMaxIdNew}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-
-    EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
-}
-
-TEST_P(HapticGeneratorScalesTest, SetAndUpdateVector) {
-    EXPECT_NO_FATAL_FAILURE(
-            addHapticScaleParam({kHapticScale, kHapticScaleWithMaxId, kHapticScaleWithMinId}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(
-            {kHapticScaleNew, kHapticScaleWithMaxIdNew, kHapticScaleWithMinIdNew}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-
-    EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
-}
-
-TEST_P(HapticGeneratorScalesTest, SetAndUpdateMultipleVector) {
-    EXPECT_NO_FATAL_FAILURE(
-            addHapticScaleParam({kHapticScale, kHapticScaleWithMaxId, kHapticScaleWithMinId}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(
-            {kHapticScaleNew, kHapticScaleWithMaxIdNew, kHapticScaleWithMinIdNew}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-    EXPECT_NO_FATAL_FAILURE(
-            addHapticScaleParam({kHapticScale, kHapticScaleWithMaxId, kHapticScaleWithMinId}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-
-    EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
-}
-
-TEST_P(HapticGeneratorScalesTest, SetOneAndAddMoreVector) {
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScale}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMaxId, kHapticScaleWithMinId}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-
-    EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
-}
-
-TEST_P(HapticGeneratorScalesTest, SetMultipleAndAddOneVector) {
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMaxId, kHapticScaleWithMinId}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-    EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScale}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-
-    EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
-}
-
-TEST_P(HapticGeneratorScalesTest, SetMultipleVectorRepeat) {
-    EXPECT_NO_FATAL_FAILURE(
-            addHapticScaleParam({kHapticScaleWithMaxId, kHapticScale, kHapticScaleWithMinId}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-    EXPECT_NO_FATAL_FAILURE(
-            addHapticScaleParam({kHapticScaleWithMaxId, kHapticScale, kHapticScaleWithMinId}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-    EXPECT_NO_FATAL_FAILURE(
-            addHapticScaleParam({kHapticScaleWithMaxId, kHapticScale, kHapticScaleWithMinId}));
-    EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
-
-    EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
-}
-
-INSTANTIATE_TEST_SUITE_P(
-        HapticGeneratorScalesTest, HapticGeneratorScalesTest,
-        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                IFactory::descriptor, getEffectTypeUuidHapticGenerator()))),
-        [](const testing::TestParamInfo<HapticGeneratorScalesTest::ParamType>& info) {
-            auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               toString(descriptor.common.id.uuid);
-            std::replace_if(
-                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
-            return name;
-        });
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorScalesTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorDataTest);
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
index 1fe8beb..ace0597 100644
--- a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
@@ -32,7 +32,6 @@
 using aidl::android::hardware::audio::effect::Parameter;
 using android::hardware::audio::common::testing::detail::TestExecutionTracer;
 
-static constexpr float kMaxAudioSample = 1;
 static constexpr int kZeroGain = 0;
 static constexpr int kMaxGain = std::numeric_limits<int>::max();
 static constexpr int kMinGain = std::numeric_limits<int>::min();
@@ -154,12 +153,13 @@
   public:
     LoudnessEnhancerDataTest() {
         std::tie(mFactory, mDescriptor) = GetParam();
-        mBufferSize = kFrameCount *
-                      getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
-                              AudioChannelLayout::LAYOUT_STEREO));
-        generateInputBuffer();
+        size_t channelCount = getChannelCount(
+                AudioChannelLayout::make<AudioChannelLayout::layoutMask>(kDefaultChannelLayout));
+        mBufferSizeInFrames = kFrameCount * channelCount;
+        mInputBuffer.resize(mBufferSizeInFrames);
+        generateInputBuffer(mInputBuffer, 0, true, channelCount, kMaxAudioSampleValue);
 
-        mOutputBuffer.resize(mBufferSize);
+        mOutputBuffer.resize(mBufferSizeInFrames);
     }
 
     void SetUp() override {
@@ -177,14 +177,6 @@
         TearDownLoudnessEnhancer();
     }
 
-    // Fill inputBuffer with random values between -kMaxAudioSample to kMaxAudioSample
-    void generateInputBuffer() {
-        for (size_t i = 0; i < mBufferSize; i++) {
-            mInputBuffer.push_back(((static_cast<float>(std::rand()) / RAND_MAX) * 2 - 1) *
-                                   kMaxAudioSample);
-        }
-    }
-
     // Add gains to the mInputBuffer and store processed output to mOutputBuffer
     void processAndWriteToOutput() {
         // Check AidlMessageQueues are not null
@@ -220,7 +212,7 @@
     }
 
     void assertSequentialGains(const std::vector<int>& gainValues, bool isIncreasing) {
-        std::vector<float> baseOutput(mBufferSize);
+        std::vector<float> baseOutput(mBufferSizeInFrames);
 
         // Process a reference output buffer with 0 gain which gives compressed input values
         binder_exception_t expected;
@@ -257,7 +249,7 @@
 
     std::vector<float> mInputBuffer;
     std::vector<float> mOutputBuffer;
-    size_t mBufferSize;
+    size_t mBufferSizeInFrames;
 };
 
 TEST_P(LoudnessEnhancerDataTest, IncreasingGains) {
@@ -296,10 +288,10 @@
     setParameters(kMaxGain, expected);
     ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput());
 
-    // Validate that mOutputBuffer reaches to kMaxAudioSample for INT_MAX gain
+    // Validate that mOutputBuffer reaches to kMaxAudioSampleValue for INT_MAX gain
     for (size_t i = 0; i < mOutputBuffer.size(); i++) {
         if (mInputBuffer[i] != 0) {
-            EXPECT_NEAR(kMaxAudioSample, abs(mOutputBuffer[i]), kAbsError);
+            EXPECT_NEAR(kMaxAudioSampleValue, abs(mOutputBuffer[i]), kAbsError);
         } else {
             ASSERT_EQ(mOutputBuffer[i], mInputBuffer[i]);
         }
diff --git a/audio/aidl/vts/VtsHalNSTargetTest.cpp b/audio/aidl/vts/VtsHalNSTargetTest.cpp
index a50e1b4..c5a9bad 100644
--- a/audio/aidl/vts/VtsHalNSTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalNSTargetTest.cpp
@@ -140,12 +140,12 @@
 };
 
 TEST_P(NSParamTest, SetAndGetLevel) {
-    EXPECT_NO_FATAL_FAILURE(addLevelParam(mLevel));
+    addLevelParam(mLevel);
     SetAndGetParameters();
 }
 
 TEST_P(NSParamTest, SetAndGetType) {
-    EXPECT_NO_FATAL_FAILURE(addLevelParam(mLevel));
+    addLevelParam(mLevel);
     SetAndGetParameters();
 }
 
diff --git a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
index 542f0d8..f127c81 100644
--- a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
@@ -81,7 +81,6 @@
                                            << "\ngetParam:" << getParam.toString();
     }
 
-    static constexpr int kSamplingFrequency = 44100;
     static constexpr int kDurationMilliSec = 500;
     static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
     int mStereoChannelCount =
@@ -133,11 +132,12 @@
   public:
     PresetReverbProcessTest() {
         std::tie(mFactory, mDescriptor) = GetParam();
-        generateSineWaveInput();
+        mInput.resize(kBufferSize);
     }
 
     void SetUp() override {
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+        ASSERT_NO_FATAL_FAILURE(generateSineWave(1000 /*Input Frequency*/, mInput));
         ASSERT_NO_FATAL_FAILURE(SetUpPresetReverb());
     }
     void TearDown() override {
@@ -145,13 +145,6 @@
         ASSERT_NO_FATAL_FAILURE(TearDownPresetReverb());
     }
 
-    void generateSineWaveInput() {
-        int frequency = 1000;
-        for (size_t i = 0; i < kBufferSize; i++) {
-            mInput.push_back(sin(2 * M_PI * frequency * i / kSamplingFrequency));
-        }
-    }
-
     bool isAuxiliary() {
         return mDescriptor.common.flags.type ==
                aidl::android::hardware::audio::effect::Flags::Type::AUXILIARY;
diff --git a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
index b449f3c..c9c7172 100644
--- a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
@@ -94,8 +94,6 @@
         }
     }
 
-    static constexpr int kSamplingFrequency = 44100;
-    static constexpr int kDefaultChannelLayout = AudioChannelLayout::LAYOUT_STEREO;
     static constexpr int kDurationMilliSec = 720;
     static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
     int kChannelCount = getChannelCount(
@@ -160,17 +158,6 @@
         ASSERT_NO_FATAL_FAILURE(TearDownVirtualizer());
     }
 
-    void generateInput(std::vector<float>& buffer) {
-        if (mZeroInput) {
-            std::fill(buffer.begin(), buffer.end(), 0);
-        } else {
-            int frequency = 100;
-            for (size_t i = 0; i < buffer.size(); i++) {
-                buffer[i] = sin(2 * M_PI * frequency * i / kSamplingFrequency);
-            }
-        }
-    }
-
     static constexpr float kAbsError = 0.00001;
     bool mZeroInput;
 };
@@ -180,7 +167,11 @@
     std::vector<float> output(kBufferSize);
     std::vector<int> strengths = {250, 500, 750, 1000};
 
-    generateInput(input);
+    if (mZeroInput) {
+        std::fill(input.begin(), input.end(), 0);
+    } else {
+        ASSERT_NO_FATAL_FAILURE(generateSineWave(1000 /*Input Frequency*/, input));
+    }
 
     const float inputRmse =
             audio_utils_compute_energy_mono(input.data(), AUDIO_FORMAT_PCM_FLOAT, input.size());
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
index f215a8e..f019e2a 100644
--- a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -19,11 +19,13 @@
 #define LOG_TAG "VtsHalVisualizerTest"
 #include <android-base/logging.h>
 #include <android/binder_enums.h>
+#include <audio_utils/power.h>
 
 #include "EffectHelper.h"
 
 using namespace android;
 
+using aidl::android::hardware::audio::common::getChannelCount;
 using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer;
 using aidl::android::hardware::audio::effect::IEffect;
@@ -43,48 +45,50 @@
     PARAM_MEASUREMENT_MODE,
     PARAM_LATENCY,
 };
-using VisualizerParamTestParam =
-        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int, Visualizer::ScalingMode,
-                   Visualizer::MeasurementMode, int>;
+using VisualizerTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int,
+                                       Visualizer::ScalingMode, Visualizer::MeasurementMode, int>;
 
-class VisualizerParamTest : public ::testing::TestWithParam<VisualizerParamTestParam>,
-                            public EffectHelper {
+class VisualizerTestHelper : public EffectHelper {
   public:
-    VisualizerParamTest()
-        : mCaptureSize(std::get<PARAM_CAPTURE_SIZE>(GetParam())),
-          mScalingMode(std::get<PARAM_SCALING_MODE>(GetParam())),
-          mMeasurementMode(std::get<PARAM_MEASUREMENT_MODE>(GetParam())),
-          mLatency(std::get<PARAM_LATENCY>(GetParam())) {
-        std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+    VisualizerTestHelper(
+            std::pair<std::shared_ptr<IFactory>, Descriptor> descPair = {}, int captureSize = 128,
+            int latency = 0,
+            Visualizer::ScalingMode scalingMode = Visualizer::ScalingMode::NORMALIZED,
+            Visualizer::MeasurementMode measurementMode = Visualizer::MeasurementMode::NONE)
+        : mCaptureSize(captureSize),
+          mLatency(latency),
+          mScalingMode(scalingMode),
+          mMeasurementMode(measurementMode),
+          mInputBuffer(mBufferSizeInFrames),
+          mOutputBuffer(mBufferSizeInFrames) {
+        std::tie(mFactory, mDescriptor) = descPair;
     }
 
-    void SetUp() override {
+    void SetUpVisualizer() {
         ASSERT_NE(nullptr, mFactory);
         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
+        AudioChannelLayout inputLayout = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                AudioChannelLayout::LAYOUT_MONO);
+        AudioChannelLayout outputLayout = inputLayout;
+
         Parameter::Common common = createParamCommon(
-                0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
-                kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
-        IEffect::OpenEffectReturn ret;
-        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt, &ret, EX_NONE));
+                0 /* session */, 1 /* ioHandle */, mBufferSizeInFrames /* iSampleRate */,
+                mBufferSizeInFrames /* oSampleRate */, kInputFrameCount /* iFrameCount */,
+                kOutputFrameCount /* oFrameCount */, inputLayout, outputLayout);
+        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt, &mOpenEffectReturn, EX_NONE));
         ASSERT_NE(nullptr, mEffect);
+        mVersion = EffectFactoryHelper::getHalVersion(mFactory);
     }
 
-    void TearDown() override {
+    void TearDownVisualizer() {
         ASSERT_NO_FATAL_FAILURE(close(mEffect));
         ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+        mOpenEffectReturn = IEffect::OpenEffectReturn{};
     }
 
-    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
-    std::shared_ptr<IFactory> mFactory;
-    std::shared_ptr<IEffect> mEffect;
-    Descriptor mDescriptor;
-    int mCaptureSize;
-    Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED;
-    Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE;
-    int mLatency = 0;
-
-    void SetAndGetParameters() {
+    void SetAndGetParameters(bool* allParamsValid = nullptr) {
+        if (allParamsValid != nullptr) *allParamsValid = true;
         for (auto& it : mCommonTags) {
             auto& tag = it.first;
             auto& vs = it.second;
@@ -94,6 +98,9 @@
             ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
             const bool valid = isParameterValid<Visualizer, Range::visualizer>(vs, desc);
             const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+            if (expected == EX_ILLEGAL_ARGUMENT && allParamsValid != nullptr) {
+                *allParamsValid = false;
+            }
 
             // set parameter
             Parameter expectParam;
@@ -137,39 +144,180 @@
                 {Visualizer::latencyMs, Visualizer::make<Visualizer::latencyMs>(latency)});
     }
 
-    static std::unordered_set<Visualizer::MeasurementMode> getMeasurementModeValues() {
-        return {ndk::enum_range<Visualizer::MeasurementMode>().begin(),
-                ndk::enum_range<Visualizer::MeasurementMode>().end()};
-    }
-
     static std::unordered_set<Visualizer::ScalingMode> getScalingModeValues() {
         return {ndk::enum_range<Visualizer::ScalingMode>().begin(),
                 ndk::enum_range<Visualizer::ScalingMode>().end()};
     }
 
+    static constexpr long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+    const size_t mChannelCount =
+            getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                    AudioChannelLayout::LAYOUT_MONO));
+    const size_t mBufferSizeInFrames = kInputFrameCount * mChannelCount;
+    const int mCaptureSize;
+    const int mLatency;
+    const Visualizer::ScalingMode mScalingMode;
+    const Visualizer::MeasurementMode mMeasurementMode;
+    int mVersion;
+    std::vector<float> mInputBuffer;
+    std::vector<float> mOutputBuffer;
+    std::shared_ptr<IEffect> mEffect;
+    std::shared_ptr<IFactory> mFactory;
+    Descriptor mDescriptor;
+    IEffect::OpenEffectReturn mOpenEffectReturn;
+
   private:
     std::vector<std::pair<Visualizer::Tag, Visualizer>> mCommonTags;
     void CleanUp() { mCommonTags.clear(); }
 };
 
+class VisualizerParamTest : public ::testing::TestWithParam<VisualizerTestParam>,
+                            public VisualizerTestHelper {
+  public:
+    VisualizerParamTest()
+        : VisualizerTestHelper(std::get<PARAM_INSTANCE_NAME>(GetParam()),
+                               std::get<PARAM_CAPTURE_SIZE>(GetParam()),
+                               std::get<PARAM_LATENCY>(GetParam()),
+                               std::get<PARAM_SCALING_MODE>(GetParam()),
+                               std::get<PARAM_MEASUREMENT_MODE>(GetParam())) {
+        generateInputBuffer(mInputBuffer, 0, true, mChannelCount, kMaxAudioSampleValue);
+    }
+
+    void SetUp() override { SetUpVisualizer(); }
+
+    void TearDown() override { TearDownVisualizer(); }
+
+    static std::unordered_set<Visualizer::MeasurementMode> getMeasurementModeValues() {
+        return {ndk::enum_range<Visualizer::MeasurementMode>().begin(),
+                ndk::enum_range<Visualizer::MeasurementMode>().end()};
+    }
+};
+
 TEST_P(VisualizerParamTest, SetAndGetCaptureSize) {
-    EXPECT_NO_FATAL_FAILURE(addCaptureSizeParam(mCaptureSize));
-    SetAndGetParameters();
+    addCaptureSizeParam(mCaptureSize);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 TEST_P(VisualizerParamTest, SetAndGetScalingMode) {
-    EXPECT_NO_FATAL_FAILURE(addScalingModeParam(mScalingMode));
-    SetAndGetParameters();
+    addScalingModeParam(mScalingMode);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 TEST_P(VisualizerParamTest, SetAndGetMeasurementMode) {
-    EXPECT_NO_FATAL_FAILURE(addMeasurementModeParam(mMeasurementMode));
-    SetAndGetParameters();
+    addMeasurementModeParam(mMeasurementMode);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
 }
 
 TEST_P(VisualizerParamTest, SetAndGetLatency) {
-    EXPECT_NO_FATAL_FAILURE(addLatencyParam(mLatency));
-    SetAndGetParameters();
+    addLatencyParam(mLatency);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
+}
+
+TEST_P(VisualizerParamTest, testCaptureSampleBufferSizeAndOutput) {
+    SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+
+    bool allParamsValid = true;
+    addCaptureSizeParam(mCaptureSize);
+    addScalingModeParam(mScalingMode);
+    addMeasurementModeParam(mMeasurementMode);
+    addLatencyParam(mLatency);
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters(&allParamsValid));
+
+    Parameter getParam;
+    Parameter::Id id;
+    Visualizer::Id vsId;
+    vsId.set<Visualizer::Id::commonTag>(Visualizer::captureSampleBuffer);
+    id.set<Parameter::Id::visualizerTag>(vsId);
+    EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam)) << " with: " << id.toString();
+
+    ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput(mInputBuffer, mOutputBuffer, mEffect,
+                                                    &mOpenEffectReturn, mVersion));
+    ASSERT_EQ(mInputBuffer, mOutputBuffer);
+
+    if (allParamsValid) {
+        std::vector<uint8_t> captureBuffer = getParam.get<Parameter::specific>()
+                                                     .get<Parameter::Specific::visualizer>()
+                                                     .get<Visualizer::captureSampleBuffer>();
+        ASSERT_EQ((size_t)mCaptureSize, captureBuffer.size());
+    }
+}
+
+class VisualizerDataTest : public ::testing::TestWithParam<VisualizerTestParam>,
+                           public VisualizerTestHelper {
+  public:
+    VisualizerDataTest()
+        : VisualizerTestHelper(std::get<PARAM_INSTANCE_NAME>(GetParam()),
+                               std::get<PARAM_CAPTURE_SIZE>(GetParam()),
+                               std::get<PARAM_LATENCY>(GetParam()),
+                               std::get<PARAM_SCALING_MODE>(GetParam()),
+                               std::get<PARAM_MEASUREMENT_MODE>(GetParam())) {}
+
+    void SetUp() override { SetUpVisualizer(); }
+
+    void TearDown() override { TearDownVisualizer(); }
+};
+
+TEST_P(VisualizerDataTest, testScalingModeParameters) {
+    SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+
+    // This test holds true for the following range
+    static_assert(kMaxAudioSampleValue <= 1.0 && kMaxAudioSampleValue > 0.0,
+                  "Valid range of kMaxAudioSample value for the test: (0.0, 1.0]");
+
+    constexpr float kPowerToleranceDb = 0.5;
+
+    ASSERT_NO_FATAL_FAILURE(generateSineWave(1000, mInputBuffer, 1.0, mBufferSizeInFrames,
+                                             AudioChannelLayout::LAYOUT_MONO));
+    const float expectedPowerNormalized = audio_utils_compute_power_mono(
+            mInputBuffer.data(), AUDIO_FORMAT_PCM_FLOAT, mInputBuffer.size());
+
+    const std::vector<float> testMaxAudioSampleValueList = {
+            0.25 * kMaxAudioSampleValue, 0.5 * kMaxAudioSampleValue, 0.75 * kMaxAudioSampleValue,
+            kMaxAudioSampleValue};
+
+    Parameter::Id idCsb;
+    Visualizer::Id vsIdCsb;
+    vsIdCsb.set<Visualizer::Id::commonTag>(Visualizer::captureSampleBuffer);
+    idCsb.set<Parameter::Id::visualizerTag>(vsIdCsb);
+
+    for (float maxAudioSampleValue : testMaxAudioSampleValueList) {
+        bool allParamsValid = true;
+        addCaptureSizeParam(mCaptureSize);
+        addScalingModeParam(mScalingMode);
+        addLatencyParam(mLatency);
+        ASSERT_NO_FATAL_FAILURE(SetAndGetParameters(&allParamsValid));
+
+        ASSERT_NO_FATAL_FAILURE(generateSineWave(std::vector<int>{1000}, mInputBuffer,
+                                                 maxAudioSampleValue, mBufferSizeInFrames,
+                                                 AudioChannelLayout::LAYOUT_MONO));
+
+        // The stop and reset calls to the effect are made towards the end in order to fetch the
+        // captureSampleBuffer values
+        ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput(mInputBuffer, mOutputBuffer, mEffect,
+                                                        &mOpenEffectReturn, mVersion, 1, false));
+        if (allParamsValid) {
+            Parameter getParam;
+            EXPECT_STATUS(EX_NONE, mEffect->getParameter(idCsb, &getParam))
+                    << " with: " << idCsb.toString();
+            std::vector<uint8_t> captureBuffer = getParam.get<Parameter::specific>()
+                                                         .get<Parameter::Specific::visualizer>()
+                                                         .get<Visualizer::captureSampleBuffer>();
+            ASSERT_EQ((size_t)mCaptureSize, captureBuffer.size());
+
+            float currPowerCsb = audio_utils_compute_power_mono(
+                    captureBuffer.data(), AUDIO_FORMAT_PCM_8_BIT, mCaptureSize);
+
+            if (mScalingMode == Visualizer::ScalingMode::NORMALIZED) {
+                EXPECT_NEAR(currPowerCsb, expectedPowerNormalized, kPowerToleranceDb);
+            } else {
+                float powerI = audio_utils_compute_power_mono(
+                        mInputBuffer.data(), AUDIO_FORMAT_PCM_FLOAT, mInputBuffer.size());
+                EXPECT_NEAR(currPowerCsb, powerI, kPowerToleranceDb);
+            }
+        }
+        ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+        ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+    }
 }
 
 std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kDescPair;
@@ -181,7 +329,7 @@
                 testing::ValuesIn(EffectHelper::getTestValueSet<Visualizer, int, Range::visualizer,
                                                                 Visualizer::captureSamples>(
                         kDescPair, EffectHelper::expandTestValueBasic<int>)),
-                testing::ValuesIn(VisualizerParamTest::getScalingModeValues()),
+                testing::ValuesIn(VisualizerTestHelper::getScalingModeValues()),
                 testing::ValuesIn(VisualizerParamTest::getMeasurementModeValues()),
                 testing::ValuesIn(EffectHelper::getTestValueSet<Visualizer, int, Range::visualizer,
                                                                 Visualizer::latencyMs>(
@@ -205,6 +353,35 @@
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VisualizerParamTest);
 
+INSTANTIATE_TEST_SUITE_P(
+        VisualizerDataTest, VisualizerDataTest,
+        ::testing::Combine(
+                testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
+                                          IFactory::descriptor, getEffectTypeUuidVisualizer())),
+                testing::Values(128),  // captureSize
+                testing::ValuesIn(VisualizerTestHelper::getScalingModeValues()),
+                testing::Values(Visualizer::MeasurementMode::PEAK_RMS),
+                testing::Values(0)  // latency
+                ),
+        [](const testing::TestParamInfo<VisualizerDataTest::ParamType>& info) {
+            auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+            std::string captureSize = std::to_string(std::get<PARAM_CAPTURE_SIZE>(info.param));
+            std::string scalingMode = aidl::android::hardware::audio::effect::toString(
+                    std::get<PARAM_SCALING_MODE>(info.param));
+            std::string measurementMode = aidl::android::hardware::audio::effect::toString(
+                    std::get<PARAM_MEASUREMENT_MODE>(info.param));
+            std::string latency = std::to_string(std::get<PARAM_LATENCY>(info.param));
+
+            std::string name = getPrefix(descriptor) + "_captureSize" + captureSize +
+                               "_scalingMode" + scalingMode + "_measurementMode" + measurementMode +
+                               "_latency" + latency;
+            std::replace_if(
+                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+            return name;
+        });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VisualizerDataTest);
+
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
     ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
diff --git a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
index 2c21d2e..0b68b02 100644
--- a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
@@ -66,7 +66,7 @@
 
     void initFrameCount() {
         int channelCount = getChannelCount(
-                AudioChannelLayout::make<AudioChannelLayout::layoutMask>(kDefaultChannelLayout));
+                AudioChannelLayout::make<AudioChannelLayout::layoutMask>(mChannelLayout));
         mInputFrameCount = kBufferSize / channelCount;
         mOutputFrameCount = kBufferSize / channelCount;
     }
@@ -93,11 +93,10 @@
         }
     }
 
-    static constexpr int kSamplingFrequency = 44100;
-    static constexpr int kDurationMilliSec = 720;
+    static constexpr int kDurationMilliSec = 1440;
     static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
     static constexpr int kMinLevel = -96;
-    static constexpr int kDefaultChannelLayout = AudioChannelLayout::LAYOUT_STEREO;
+    static constexpr int mChannelLayout = kDefaultChannelLayout;
     long mInputFrameCount, mOutputFrameCount;
     std::shared_ptr<IFactory> mFactory;
     std::shared_ptr<IEffect> mEffect;
@@ -108,16 +107,13 @@
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
  * VtsAudioEffectTargetTest.
  */
-enum ParamName { PARAM_INSTANCE_NAME, PARAM_LEVEL, PARAM_MUTE };
-using VolumeParamTestParam =
-        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int, bool>;
+enum VolumeLevelParamName { PARAM_INSTANCE_NAME, PARAM_LEVEL };
+using VolumeLevelTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
 
-class VolumeParamTest : public ::testing::TestWithParam<VolumeParamTestParam>,
-                        public VolumeControlHelper {
+class VolumeLevelParamTest : public ::testing::TestWithParam<VolumeLevelTestParam>,
+                             public VolumeControlHelper {
   public:
-    VolumeParamTest()
-        : mParamLevel(std::get<PARAM_LEVEL>(GetParam())),
-          mParamMute(std::get<PARAM_MUTE>(GetParam())) {
+    VolumeLevelParamTest() : mParamLevel(std::get<PARAM_LEVEL>(GetParam())) {
         std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
     }
 
@@ -125,13 +121,31 @@
     void TearDown() override { TearDownVolumeControl(); }
 
     int mParamLevel = 0;
-    bool mParamMute = false;
 };
 
-TEST_P(VolumeParamTest, SetAndGetParams) {
+TEST_P(VolumeLevelParamTest, SetAndGetParams) {
     ASSERT_NO_FATAL_FAILURE(
             setAndVerifyParameters(Volume::levelDb, mParamLevel,
                                    isLevelValid(mParamLevel) ? EX_NONE : EX_ILLEGAL_ARGUMENT));
+}
+
+enum VolumeMuteParamName { MUTE_PARAM_INSTANCE_NAME, PARAM_MUTE };
+using VolumeMuteTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, bool>;
+
+class VolumeMuteParamTest : public ::testing::TestWithParam<VolumeMuteTestParam>,
+                            public VolumeControlHelper {
+  public:
+    VolumeMuteParamTest() : mParamMute(std::get<PARAM_MUTE>(GetParam())) {
+        std::tie(mFactory, mDescriptor) = std::get<MUTE_PARAM_INSTANCE_NAME>(GetParam());
+    }
+
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpVolumeControl()); }
+    void TearDown() override { TearDownVolumeControl(); }
+
+    bool mParamMute = false;
+};
+
+TEST_P(VolumeMuteParamTest, SetAndGetParams) {
     ASSERT_NO_FATAL_FAILURE(setAndVerifyParameters(Volume::mute, mParamMute, EX_NONE));
 }
 
@@ -148,8 +162,6 @@
         mInputMag.resize(mTestFrequencies.size());
         mBinOffsets.resize(mTestFrequencies.size());
         roundToFreqCenteredToFftBin(mTestFrequencies, mBinOffsets, kBinWidth);
-        generateMultiTone(mTestFrequencies, mInput, kSamplingFrequency);
-        mInputMag = calculateMagnitude(mInput, mBinOffsets, kNPointFFT);
     }
 
     std::vector<int> calculatePercentageDiff(const std::vector<float>& outputMag) {
@@ -169,6 +181,11 @@
         SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
         // Skips test fixture if api_level <= 34 (__ANDROID_API_U__).
         if (kVsrApiLevel <= __ANDROID_API_U__) GTEST_SKIP();
+        ASSERT_NO_FATAL_FAILURE(generateSineWave(mTestFrequencies, mInput, 1.0, kSamplingFrequency,
+                                                 mChannelLayout));
+        ASSERT_NO_FATAL_FAILURE(
+                calculateAndVerifyMagnitude(mInputMag, mChannelLayout, mInput, mBinOffsets));
+
         ASSERT_NO_FATAL_FAILURE(SetUpVolumeControl());
     }
     void TearDown() override {
@@ -180,7 +197,6 @@
     const int kVsrApiLevel;
     static constexpr int kMaxAudioSample = 1;
     static constexpr int kTransitionDuration = 300;
-    static constexpr int kNPointFFT = 16384;
     static constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
     static constexpr size_t offset = kSamplingFrequency * kTransitionDuration / 1000;
     static constexpr float kBaseLevel = 0;
@@ -204,7 +220,9 @@
     ASSERT_NO_FATAL_FAILURE(setAndVerifyParameters(Volume::levelDb, kBaseLevel, EX_NONE));
     ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput(mInput, output, mEffect, &mOpenEffectReturn));
 
-    outputMag = calculateMagnitude(output, mBinOffsets, kNPointFFT);
+    ASSERT_NO_FATAL_FAILURE(
+            calculateAndVerifyMagnitude(outputMag, mChannelLayout, output, mBinOffsets));
+
     diffs = calculatePercentageDiff(outputMag);
 
     for (size_t i = 0; i < diffs.size(); i++) {
@@ -217,7 +235,10 @@
     ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput(mInput, output, mEffect, &mOpenEffectReturn));
 
     std::vector<float> subOutputMute(output.begin() + offset, output.end());
-    outputMag = calculateMagnitude(subOutputMute, mBinOffsets, kNPointFFT);
+
+    ASSERT_NO_FATAL_FAILURE(
+            calculateAndVerifyMagnitude(outputMag, mChannelLayout, subOutputMute, mBinOffsets));
+
     diffs = calculatePercentageDiff(outputMag);
 
     for (size_t i = 0; i < diffs.size(); i++) {
@@ -225,7 +246,9 @@
     }
 
     // Verifying Fade out
-    outputMag = calculateMagnitude(output, mBinOffsets, kNPointFFT);
+    ASSERT_NO_FATAL_FAILURE(
+            calculateAndVerifyMagnitude(outputMag, mChannelLayout, output, mBinOffsets));
+
     diffs = calculatePercentageDiff(outputMag);
 
     for (size_t i = 0; i < diffs.size(); i++) {
@@ -239,7 +262,9 @@
 
     std::vector<float> subOutputUnmute(output.begin() + offset, output.end());
 
-    outputMag = calculateMagnitude(subOutputUnmute, mBinOffsets, kNPointFFT);
+    ASSERT_NO_FATAL_FAILURE(
+            calculateAndVerifyMagnitude(outputMag, mChannelLayout, subOutputUnmute, mBinOffsets));
+
     diffs = calculatePercentageDiff(outputMag);
 
     for (size_t i = 0; i < diffs.size(); i++) {
@@ -247,7 +272,9 @@
     }
 
     // Verifying Fade in
-    outputMag = calculateMagnitude(output, mBinOffsets, kNPointFFT);
+    ASSERT_NO_FATAL_FAILURE(
+            calculateAndVerifyMagnitude(outputMag, mChannelLayout, output, mBinOffsets));
+
     diffs = calculatePercentageDiff(outputMag);
 
     for (size_t i = 0; i < diffs.size(); i++) {
@@ -269,7 +296,9 @@
     ASSERT_NO_FATAL_FAILURE(
             processAndWriteToOutput(mInput, baseOutput, mEffect, &mOpenEffectReturn));
 
-    outputMag = calculateMagnitude(baseOutput, mBinOffsets, kNPointFFT);
+    ASSERT_NO_FATAL_FAILURE(
+            calculateAndVerifyMagnitude(outputMag, mChannelLayout, baseOutput, mBinOffsets));
+
     baseDiffs = calculatePercentageDiff(outputMag);
 
     for (int level : decreasingLevels) {
@@ -284,7 +313,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 processAndWriteToOutput(mInput, output, mEffect, &mOpenEffectReturn));
 
-        outputMag = calculateMagnitude(output, mBinOffsets, kNPointFFT);
+        ASSERT_NO_FATAL_FAILURE(
+                calculateAndVerifyMagnitude(outputMag, mChannelLayout, output, mBinOffsets));
+
         diffs = calculatePercentageDiff(outputMag);
 
         // Decrease in volume level results in greater magnitude difference
@@ -298,25 +329,40 @@
 
 std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kDescPair;
 INSTANTIATE_TEST_SUITE_P(
-        VolumeTest, VolumeParamTest,
+        VolumeTest, VolumeLevelParamTest,
         ::testing::Combine(
                 testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
                                           IFactory::descriptor, getEffectTypeUuidVolume())),
                 testing::ValuesIn(
                         EffectHelper::getTestValueSet<Volume, int, Range::volume, Volume::levelDb>(
-                                kDescPair, EffectHelper::expandTestValueBasic<int>)),
-                testing::Bool() /* mute */),
-        [](const testing::TestParamInfo<VolumeParamTest::ParamType>& info) {
+                                kDescPair, EffectHelper::expandTestValueBasic<int>))),
+        [](const testing::TestParamInfo<VolumeLevelParamTest::ParamType>& info) {
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
             std::string level = std::to_string(std::get<PARAM_LEVEL>(info.param));
-            std::string mute = std::to_string(std::get<PARAM_MUTE>(info.param));
-            std::string name = getPrefix(descriptor) + "_level" + level + "_mute" + mute;
+            std::string name = getPrefix(descriptor) + "_level" + level;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
         });
 
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VolumeParamTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VolumeLevelParamTest);
+
+INSTANTIATE_TEST_SUITE_P(
+        VolumeTest, VolumeMuteParamTest,
+        ::testing::Combine(
+                testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
+                                          IFactory::descriptor, getEffectTypeUuidVolume())),
+                testing::Bool() /* mute */),
+        [](const testing::TestParamInfo<VolumeMuteParamTest::ParamType>& info) {
+            auto descriptor = std::get<MUTE_PARAM_INSTANCE_NAME>(info.param).second;
+            std::string mute = std::to_string(std::get<PARAM_MUTE>(info.param));
+            std::string name = getPrefix(descriptor) + "_mute" + mute;
+            std::replace_if(
+                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+            return name;
+        });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VolumeMuteParamTest);
 
 INSTANTIATE_TEST_SUITE_P(VolumeTest, VolumeDataTest,
                          testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
diff --git a/audio/common/5.0/Android.bp b/audio/common/5.0/Android.bp
index 02f66a3..d9c4f58 100644
--- a/audio/common/5.0/Android.bp
+++ b/audio/common/5.0/Android.bp
@@ -23,6 +23,6 @@
     gen_java_constants: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.btservices",
+        "com.android.bt",
     ],
 }
diff --git a/audio/common/all-versions/default/7.0/HidlUtils.cpp b/audio/common/all-versions/default/7.0/HidlUtils.cpp
index f89c898..bc056e2 100644
--- a/audio/common/all-versions/default/7.0/HidlUtils.cpp
+++ b/audio/common/all-versions/default/7.0/HidlUtils.cpp
@@ -1025,7 +1025,7 @@
             result = BAD_VALUE;
         }
     }
-    std::string fullHalTags{std::move(halTagsBuffer.str())};
+    std::string fullHalTags{halTagsBuffer.str()};
     strncpy(halTags, fullHalTags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
     CONVERT_CHECKED(fullHalTags.length() <= AUDIO_ATTRIBUTES_TAGS_MAX_SIZE ? NO_ERROR : BAD_VALUE,
                     result);
diff --git a/audio/policy/1.0/vts/functional/Android.bp b/audio/policy/1.0/vts/functional/Android.bp
index b32c223..c2335e4 100644
--- a/audio/policy/1.0/vts/functional/Android.bp
+++ b/audio/policy/1.0/vts/functional/Android.bp
@@ -17,8 +17,9 @@
         "libxml2",
         "liblog",
         "libmedia_helper",
-        "libaudiopolicyengine_config",
+        "libaudiopolicycapengine_config",
         "libaudiopolicycomponents",
+        "libaudiopolicyengine_config",
         "libaudiopolicyengineconfigurable_pfwwrapper",
         "android.hardware.audio.common.test.utility",
         "libparameter",
diff --git a/audio/policy/1.0/xml/api/current.txt b/audio/policy/1.0/xml/api/current.txt
index 01d77d7..19a8123 100644
--- a/audio/policy/1.0/xml/api/current.txt
+++ b/audio/policy/1.0/xml/api/current.txt
@@ -162,7 +162,9 @@
   public static class ProductStrategies.ProductStrategy {
     ctor public ProductStrategies.ProductStrategy();
     method public java.util.List<audio.policy.V1_0.AttributesGroup> getAttributesGroup();
+    method public int getId();
     method public String getName();
+    method public void setId(int);
     method public void setName(String);
   }
 
diff --git a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
index 40396bb..2b86049 100644
--- a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
+++ b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
@@ -105,6 +105,7 @@
                         <xs:element name="AttributesGroup" type="AttributesGroup" minOccurs="1" maxOccurs="unbounded"/>
                     </xs:sequence>
                     <xs:attribute name="name" type="xs:string" use="required"/>
+                    <xs:attribute name="id" type="xs:int" use="optional"/>
                 </xs:complexType>
             </xs:element>
         </xs:sequence>
diff --git a/authsecret/1.0/vts/functional/Android.bp b/authsecret/1.0/vts/functional/Android.bp
index 853b4dd..388cf3c 100644
--- a/authsecret/1.0/vts/functional/Android.bp
+++ b/authsecret/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/authsecret/aidl/Android.bp b/authsecret/aidl/Android.bp
index 90e128d..b5e4e3d 100644
--- a/authsecret/aidl/Android.bp
+++ b/authsecret/aidl/Android.bp
@@ -10,6 +10,7 @@
 aidl_interface {
     name: "android.hardware.authsecret",
     vendor_available: true,
+    frozen: true,
     srcs: ["android/hardware/authsecret/*.aidl"],
     stability: "vintf",
     backend: {
diff --git a/authsecret/aidl/vts/Android.bp b/authsecret/aidl/vts/Android.bp
index 5ec9947..bde1a40 100644
--- a/authsecret/aidl/vts/Android.bp
+++ b/authsecret/aidl/vts/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/automotive/TEST_MAPPING b/automotive/TEST_MAPPING
index c64c880..483a85f 100644
--- a/automotive/TEST_MAPPING
+++ b/automotive/TEST_MAPPING
@@ -19,10 +19,58 @@
     	"name": "CtsCarBuiltinApiHostTestCases"
     },
     {
-      "name": "CarServiceTest"
+      "name": "CarServiceAudioTest"
+    },
+    {
+      "name": "CarServiceCarTest"
+    },
+    {
+      "name": "CarServiceClusterTest"
+    },
+    {
+      "name": "CarServiceDiagnosticTest"
+    },
+    {
+      "name": "CarServiceDrivingStateTest"
+    },
+    {
+      "name": "CarServiceEvsTest"
+    },
+    {
+      "name": "CarServiceGarageModeTest"
+    },
+    {
+      "name": "CarServiceInputTest"
+    },
+    {
+      "name": "CarServiceOsTest"
+    },
+    {
+      "name": "CarServicePmTest"
+    },
+    {
+      "name": "CarServicePowerTest"
+    },
+    {
+      "name": "CarServicePropertyTest"
+    },
+    {
+      "name": "CarServiceRemoteAccessTest"
+    },
+    {
+      "name": "CarServiceStorageMonitoringTest"
+    },
+    {
+      "name": "CarServiceTelemetryTest"
     },
     {
       "name": "CarServiceUnitTest"
+    },
+    {
+      "name": "CarServiceVmsTest"
+    },
+    {
+      "name": "CarServiceWatchdogTest"
     }
   ]
 }
\ No newline at end of file
diff --git a/automotive/audiocontrol/1.0/vts/functional/Android.bp b/automotive/audiocontrol/1.0/vts/functional/Android.bp
index 15c480a..fe5be81 100644
--- a/automotive/audiocontrol/1.0/vts/functional/Android.bp
+++ b/automotive/audiocontrol/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_automotive",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/automotive/audiocontrol/2.0/vts/functional/Android.bp b/automotive/audiocontrol/2.0/vts/functional/Android.bp
index cb7a54d..597aaa3 100644
--- a/automotive/audiocontrol/2.0/vts/functional/Android.bp
+++ b/automotive/audiocontrol/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_automotive",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/automotive/can/1.0/default/libnetdevice/Android.bp b/automotive/can/1.0/default/libnetdevice/Android.bp
index 653e773..b42893e 100644
--- a/automotive/can/1.0/default/libnetdevice/Android.bp
+++ b/automotive/can/1.0/default/libnetdevice/Android.bp
@@ -23,10 +23,19 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-cc_library_static {
-    name: "android.hardware.automotive.can@libnetdevice",
-    defaults: ["android.hardware.automotive.can@defaults"],
+cc_defaults {
+    name: "libnetdevice-common",
     vendor_available: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
+    ],
+    shared_libs: [
+        "libbase",
+        "libutils",
+    ],
     srcs: [
         "can.cpp",
         "common.cpp",
@@ -40,3 +49,14 @@
         "libnl++",
     ],
 }
+
+// TODO: migrate to "libnetdevice" and remove
+cc_library_static {
+    name: "android.hardware.automotive.can@libnetdevice",
+    defaults: ["libnetdevice-common"],
+}
+
+cc_library_static {
+    name: "libnetdevice",
+    defaults: ["libnetdevice-common"],
+}
diff --git a/automotive/can/1.0/default/libnl++/Android.bp b/automotive/can/1.0/default/libnl++/Android.bp
index 01c1e55..d929d84 100644
--- a/automotive/can/1.0/default/libnl++/Android.bp
+++ b/automotive/can/1.0/default/libnl++/Android.bp
@@ -25,8 +25,17 @@
 
 cc_library_static {
     name: "libnl++",
-    defaults: ["android.hardware.automotive.can@defaults"],
     vendor_available: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
+    ],
+    shared_libs: [
+        "libbase",
+        "libutils",
+    ],
     srcs: [
         "protocols/common/Empty.cpp",
         "protocols/common/Error.cpp",
diff --git a/automotive/can/1.0/vts/functional/Android.bp b/automotive/can/1.0/vts/functional/Android.bp
index 1d51492..b13ec3b 100644
--- a/automotive/can/1.0/vts/functional/Android.bp
+++ b/automotive/can/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_connectivity_telemetry",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/automotive/can/aidl/default/CanController.cpp b/automotive/can/aidl/default/CanController.cpp
index 1435a02..40332d5 100644
--- a/automotive/can/aidl/default/CanController.cpp
+++ b/automotive/can/aidl/default/CanController.cpp
@@ -20,10 +20,10 @@
 #include "CanBusSlcan.h"
 #include "CanBusVirtual.h"
 
-#include <android-base/format.h>
 #include <android-base/logging.h>
 
 #include <filesystem>
+#include <format>
 #include <fstream>
 #include <regex>
 
@@ -235,7 +235,7 @@
                                                    std::string* ifaceName) {
     *ifaceName = {};
     if (mBusesByName.find(busName) == mBusesByName.end()) {
-        return resultToStatus(Result::BAD_BUS_NAME, fmt::format("{} doesn't exist", busName));
+        return resultToStatus(Result::BAD_BUS_NAME, std::format("{} doesn't exist", busName));
     }
     *ifaceName = std::string(mBusesByName[busName]->getIfaceName());
     return ok();
@@ -245,11 +245,11 @@
     if (!isValidName(config.name)) {
         LOG(ERROR) << "Bus name " << config.name << " is invalid";
         return resultToStatus(Result::BAD_BUS_NAME,
-                              fmt::format("{} is not a valid bus name", config.name));
+                              std::format("{} is not a valid bus name", config.name));
     } else if (mBusesByName.find(config.name) != mBusesByName.end()) {
         LOG(ERROR) << "A bus named " << config.name << " already exists!";
         return resultToStatus(Result::INVALID_STATE,
-                              fmt::format("A bus named {} already exists", config.name));
+                              std::format("A bus named {} already exists", config.name));
     }
 
     if (config.interfaceId.getTag() == BusConfig::InterfaceId::Tag::virtualif) {
@@ -310,7 +310,7 @@
     if (result != Result::OK) {
         // the bus failed to come up, don't leave a broken entry in the map.
         mBusesByName.erase(config.name);
-        return resultToStatus(result, fmt::format("CanBus::up failed for {}", config.name));
+        return resultToStatus(result, std::format("CanBus::up failed for {}", config.name));
     }
 
     *ifaceName = mBusesByName[config.name]->getIfaceName();
@@ -321,11 +321,11 @@
     if (mBusesByName.find(busName) == mBusesByName.end()) {
         return resultToStatus(
                 Result::UNKNOWN_ERROR,
-                fmt::format("Couldn't bring down {}, because it doesn't exist", busName));
+                std::format("Couldn't bring down {}, because it doesn't exist", busName));
     }
     Result result = mBusesByName[busName]->down();
     if (result != Result::OK) {
-        return resultToStatus(result, fmt::format("Couldn't bring down {}!", busName));
+        return resultToStatus(result, std::format("Couldn't bring down {}!", busName));
     }
     mBusesByName.erase(busName);
     return ok();
diff --git a/automotive/can/aidl/default/service.cpp b/automotive/can/aidl/default/service.cpp
index eb45167..ef04cfd 100644
--- a/automotive/can/aidl/default/service.cpp
+++ b/automotive/can/aidl/default/service.cpp
@@ -20,12 +20,11 @@
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
-namespace android::hardware::automotive::can {
-
 using namespace std::string_literals;
+using namespace android;
 using ::aidl::android::hardware::automotive::can::CanController;
 
-extern "C" int main() {
+int main() {
     base::SetDefaultTag("CanController");
     base::SetMinimumLogSeverity(base::VERBOSE);
 
@@ -40,4 +39,3 @@
     LOG(FATAL) << "CanController exited unexpectedly!";
     return EXIT_FAILURE;
 }
-}  // namespace android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/tools/configurator/canhalconfigurator.cpp b/automotive/can/aidl/default/tools/configurator/canhalconfigurator.cpp
index 94e77b4..87a4497 100644
--- a/automotive/can/aidl/default/tools/configurator/canhalconfigurator.cpp
+++ b/automotive/can/aidl/default/tools/configurator/canhalconfigurator.cpp
@@ -98,7 +98,11 @@
     return true;
 }
 
-extern "C" int main(int argc, char* argv[]) {
+}  // namespace android::hardware::automotive::can
+
+int main(int argc, char* argv[]) {
+    using namespace android::hardware::automotive::can;
+
     std::string configFilepath = static_cast<std::string>(kDefaultConfigPath);
 
     // allow for CLI specification of a config file.
@@ -114,5 +118,3 @@
     }
     return 0;
 }
-
-}  // namespace android::hardware::automotive::can
diff --git a/automotive/can/aidl/vts/functional/Android.bp b/automotive/can/aidl/vts/functional/Android.bp
index b816a49..d90164c 100644
--- a/automotive/can/aidl/vts/functional/Android.bp
+++ b/automotive/can/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_connectivity_telemetry",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/automotive/evs/1.0/vts/functional/Android.bp b/automotive/evs/1.0/vts/functional/Android.bp
index f1b57d7..bad193b 100644
--- a/automotive/evs/1.0/vts/functional/Android.bp
+++ b/automotive/evs/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_perception_virtualization",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/automotive/evs/1.1/default/EvsCamera.cpp b/automotive/evs/1.1/default/EvsCamera.cpp
index 520670a..fb598ff 100644
--- a/automotive/evs/1.1/default/EvsCamera.cpp
+++ b/automotive/evs/1.1/default/EvsCamera.cpp
@@ -495,7 +495,7 @@
         }
         if (!stored) {
             // Add a BufferRecord wrapping this handle to our set of available buffers
-            mBuffers.push_back(std::move(BufferRecord(memHandle)));
+            mBuffers.push_back(BufferRecord(memHandle));
         }
 
         mFramesAllowed++;
diff --git a/automotive/evs/1.1/vts/functional/Android.bp b/automotive/evs/1.1/vts/functional/Android.bp
index 18687bf..8f9d5c7 100644
--- a/automotive/evs/1.1/vts/functional/Android.bp
+++ b/automotive/evs/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_perception_virtualization",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/automotive/evs/aidl/Android.bp b/automotive/evs/aidl/Android.bp
index dfb15c6..8983ae4 100644
--- a/automotive/evs/aidl/Android.bp
+++ b/automotive/evs/aidl/Android.bp
@@ -28,9 +28,11 @@
         "android/hardware/automotive/evs/*.aidl",
     ],
     stability: "vintf",
+    defaults: [
+        "android.hardware.graphics.common-latest",
+    ],
     imports: [
         "android.hardware.common-V2",
-        "android.hardware.graphics.common-V5",
     ],
     backend: {
         java: {
@@ -44,20 +46,23 @@
         ndk: {
             min_sdk_version: "29",
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
             version: "1",
             imports: [
                 "android.hardware.common-V2",
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
             ],
         },
         {
             version: "2",
             imports: [
                 "android.hardware.common-V2",
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
             ],
         },
 
diff --git a/automotive/evs/aidl/impl/default/manifest_evs-default-service.xml b/automotive/evs/aidl/impl/default/manifest_evs-default-service.xml
index 50692f7..9ddc6ad 100644
--- a/automotive/evs/aidl/impl/default/manifest_evs-default-service.xml
+++ b/automotive/evs/aidl/impl/default/manifest_evs-default-service.xml
@@ -2,6 +2,6 @@
     <hal format="aidl">
         <name>android.hardware.automotive.evs</name>
         <fqname>IEvsEnumerator/hw/0</fqname>
-        <version>1</version>
+        <version>2</version>
     </hal>
 </manifest>
diff --git a/automotive/evs/aidl/impl/default/src/ConfigManager.cpp b/automotive/evs/aidl/impl/default/src/ConfigManager.cpp
index ba4cdc0..d8961d0 100644
--- a/automotive/evs/aidl/impl/default/src/ConfigManager.cpp
+++ b/automotive/evs/aidl/impl/default/src/ConfigManager.cpp
@@ -199,8 +199,8 @@
 
             CameraParam aParam;
             if (ConfigManagerUtil::convertToEvsCameraParam(nameAttr, aParam)) {
-                aCamera->controls.insert_or_assign(
-                        aParam, std::move(std::make_tuple(minVal, maxVal, stepVal)));
+                aCamera->controls.insert_or_assign(aParam,
+                                                   std::make_tuple(minVal, maxVal, stepVal));
             }
 
             ctrlElem = ctrlElem->NextSiblingElement("control");
@@ -583,8 +583,8 @@
         CameraCtrl* ptr = reinterpret_cast<CameraCtrl*>(p);
         for (size_t idx = 0; idx < sz; ++idx) {
             CameraCtrl temp = *ptr++;
-            aCamera->controls.insert_or_assign(
-                    temp.cid, std::move(std::make_tuple(temp.min, temp.max, temp.step)));
+            aCamera->controls.insert_or_assign(temp.cid,
+                                               std::make_tuple(temp.min, temp.max, temp.step));
         }
         p = reinterpret_cast<char*>(ptr);
 
@@ -689,8 +689,8 @@
         CameraCtrl* ptr = reinterpret_cast<CameraCtrl*>(p);
         for (size_t idx = 0; idx < sz; ++idx) {
             CameraCtrl temp = *ptr++;
-            aCamera->controls.insert_or_assign(
-                    temp.cid, std::move(std::make_tuple(temp.min, temp.max, temp.step)));
+            aCamera->controls.insert_or_assign(temp.cid,
+                                               std::make_tuple(temp.min, temp.max, temp.step));
         }
         p = reinterpret_cast<char*>(ptr);
 
diff --git a/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp b/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp
index 5b5cbcc..cf94e38 100644
--- a/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp
+++ b/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp
@@ -353,7 +353,7 @@
             .buffer =
                     {
                             .description = mBuffer.description,
-                            .handle = std::move(::android::dupToAidl(mBuffer.handle)),
+                            .handle = ::android::dupToAidl(mBuffer.handle),
                     },
             .pixelSizeBytes = 4,  // RGBA_8888 is 4-byte-per-pixel format
             .bufferId = mBuffer.fingerprint,
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/automotive/evs/aidl/rust_impl/Android.bp
similarity index 60%
copy from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to automotive/evs/aidl/rust_impl/Android.bp
index c7be950..ac8b90f 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/automotive/evs/aidl/rust_impl/Android.bp
@@ -14,22 +14,17 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
-
-import android.hardware.biometrics.fingerprint.AcquiredInfo;
-
-/**
- * @hide
- */
-@VintfStability
-union AcquiredInfoAndVendorCode {
-    /**
-     * Acquired info as specified in AcqauiredInfo.aidl
-     */
-    AcquiredInfo acquiredInfo = AcquiredInfo.UNKNOWN;
-
-    /**
-     * Vendor specific code
-     */
-    int vendorCode;
+rust_binary {
+    name: "android.hardware.automotive.evs-aidl-rust-service",
+    relative_install_path: "hw",
+    vendor: true,
+    srcs: ["src/*.rs"],
+    crate_root: "src/main.rs",
+    vintf_fragments: ["manifest_evs-rust-service.xml"],
+    init_rc: ["evs-rust-service.rc"],
+    rustlibs: [
+        "android.hardware.automotive.evs-V2-rust",
+        "libbinder_rs",
+        "liblog_rust",
+    ],
 }
diff --git a/automotive/evs/aidl/rust_impl/README.md b/automotive/evs/aidl/rust_impl/README.md
new file mode 100644
index 0000000..bf00aed
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/README.md
@@ -0,0 +1,21 @@
+# Rust Skeleton EVS HAL implementation.
+
+WARNING: This is not a reference EVS HAL implementation and therefore does not
+provide any actual functionality.
+
+This folder contains a skeleton EVS HAL implementation in Rust to demonstrate
+how vendors could implement their EVS HAL in Rust. To compile and run this
+implementation, please include below package to the device build script:
+
+* `android.hardware.automotive.evs-aidl-rust-service`
+
+Please note that this service will attempt to register the service as
+`IEvsEnumerator/rust/0` and therefore is also required to be declared in the
+service context by adding below line to a proper `service_contexts` file:
+
+> android.hardware.automotive.evs.IEvsEnumerator/rust/0 u:object_r:hal_evs_service:s0
+
+This implementation intentionally returns `binder::StatusCode::UNKNOWN_ERROR`
+for any API call except deprecated API for ultrasonics; the process will be
+panicked on these methods instead. Hence, this implementation does not comply
+with VTS tests and vendors must replace each method with actual implementation.
diff --git a/automotive/evs/aidl/rust_impl/evs-rust-service.rc b/automotive/evs/aidl/rust_impl/evs-rust-service.rc
new file mode 100644
index 0000000..3741b21
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/evs-rust-service.rc
@@ -0,0 +1,8 @@
+service vendor.evs-hal-rust-default /vendor/bin/hw/android.hardware.automotive.evs-aidl-rust-service
+    class early_hal
+    priority -20
+    user graphics
+    group automotive_evs camera
+    onrestart restart cardisplayproxyd
+    onrestart restart evsmanagerd
+    disabled
diff --git a/automotive/evs/aidl/rust_impl/manifest_evs-rust-service.xml b/automotive/evs/aidl/rust_impl/manifest_evs-rust-service.xml
new file mode 100644
index 0000000..813cbb2
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/manifest_evs-rust-service.xml
@@ -0,0 +1,7 @@
+<manifest version="2.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.automotive.evs</name>
+        <version>2</version>
+        <fqname>IEvsEnumerator/rust/0</fqname>
+    </hal>
+</manifest>
diff --git a/automotive/evs/aidl/rust_impl/src/default_evs_hal.rs b/automotive/evs/aidl/rust_impl/src/default_evs_hal.rs
new file mode 100644
index 0000000..72b2d53
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/src/default_evs_hal.rs
@@ -0,0 +1,113 @@
+//
+// Copyright (C) 2024 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.
+//
+
+use android_hardware_automotive_evs::aidl::android::hardware::automotive::evs::{
+    CameraDesc::CameraDesc, DisplayState::DisplayState, IEvsCamera::IEvsCamera,
+    IEvsDisplay::IEvsDisplay, IEvsEnumerator::IEvsEnumerator,
+    IEvsEnumeratorStatusCallback::IEvsEnumeratorStatusCallback,
+    IEvsUltrasonicsArray::IEvsUltrasonicsArray, Stream::Stream,
+    UltrasonicsArrayDesc::UltrasonicsArrayDesc,
+};
+
+pub struct DefaultEvsHal {}
+
+impl binder::Interface for DefaultEvsHal {}
+
+impl IEvsEnumerator for DefaultEvsHal {
+    fn closeCamera(
+        &self,
+        _: &binder::Strong<(dyn IEvsCamera + 'static)>,
+    ) -> std::result::Result<(), binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn closeDisplay(
+        &self,
+        _: &binder::Strong<(dyn IEvsDisplay + 'static)>,
+    ) -> std::result::Result<(), binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn closeUltrasonicsArray(
+        &self,
+        _: &binder::Strong<(dyn IEvsUltrasonicsArray + 'static)>,
+    ) -> std::result::Result<(), binder::Status> {
+        unimplemented!()
+    }
+
+    fn getCameraList(&self) -> std::result::Result<std::vec::Vec<CameraDesc>, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getDisplayIdList(&self) -> std::result::Result<std::vec::Vec<u8>, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getDisplayState(&self) -> std::result::Result<DisplayState, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getStreamList(
+        &self,
+        _: &CameraDesc,
+    ) -> std::result::Result<std::vec::Vec<Stream>, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getUltrasonicsArrayList(
+        &self,
+    ) -> std::result::Result<std::vec::Vec<UltrasonicsArrayDesc>, binder::Status> {
+        unimplemented!()
+    }
+
+    fn isHardware(&self) -> std::result::Result<bool, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn openCamera(
+        &self,
+        _: &str,
+        _: &Stream,
+    ) -> std::result::Result<binder::Strong<(dyn IEvsCamera + 'static)>, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn openDisplay(
+        &self,
+        _: i32,
+    ) -> std::result::Result<binder::Strong<(dyn IEvsDisplay + 'static)>, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn openUltrasonicsArray(
+        &self,
+        _: &str,
+    ) -> std::result::Result<binder::Strong<(dyn IEvsUltrasonicsArray + 'static)>, binder::Status>
+    {
+        unimplemented!()
+    }
+
+    fn registerStatusCallback(
+        &self,
+        _: &binder::Strong<(dyn IEvsEnumeratorStatusCallback + 'static)>,
+    ) -> std::result::Result<(), binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getDisplayStateById(&self, _: i32) -> std::result::Result<DisplayState, binder::Status> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+}
diff --git a/automotive/evs/aidl/rust_impl/src/main.rs b/automotive/evs/aidl/rust_impl/src/main.rs
new file mode 100644
index 0000000..df312c0
--- /dev/null
+++ b/automotive/evs/aidl/rust_impl/src/main.rs
@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2024 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.
+//
+
+mod default_evs_hal;
+
+use crate::default_evs_hal::DefaultEvsHal;
+
+use android_hardware_automotive_evs::aidl::android::hardware::automotive::evs::IEvsEnumerator::BnEvsEnumerator;
+
+use log::info;
+
+fn main() {
+    binder::ProcessState::start_thread_pool();
+
+    let service = DefaultEvsHal {};
+
+    // Register HAL implementation as rust/0 instance.
+    let service_name = "android.hardware.automotive.evs.IEvsEnumerator/rust/0";
+    let service_binder = BnEvsEnumerator::new_binder(service, binder::BinderFeatures::default());
+
+    binder::add_service(service_name, service_binder.as_binder())
+        .expect(format!("Failed to register {}.", service_name).as_str());
+    info!("EVS Hardware Enumerator is ready");
+
+    binder::ProcessState::join_thread_pool();
+
+    // In normal operation, we don't expect the thread pool to exit.
+    info!("EVS Hardware Enumerator is shutting down");
+}
diff --git a/automotive/evs/aidl/vts/Android.bp b/automotive/evs/aidl/vts/Android.bp
index e50c913..79905fa 100644
--- a/automotive/evs/aidl/vts/Android.bp
+++ b/automotive/evs/aidl/vts/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_perception_virtualization",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/automotive/evs/aidl/vts/FrameHandler.cpp b/automotive/evs/aidl/vts/FrameHandler.cpp
index e51be67..88c3643 100644
--- a/automotive/evs/aidl/vts/FrameHandler.cpp
+++ b/automotive/evs/aidl/vts/FrameHandler.cpp
@@ -50,12 +50,12 @@
         }
     } else {
         for (auto i = 0; i < handle.fds.size(); ++i) {
-            dup.fds[i] = std::move(handle.fds[i].dup());
+            dup.fds[i] = handle.fds[i].dup();
         }
     }
     dup.ints = handle.ints;
 
-    return std::move(dup);
+    return dup;
 }
 
 HardwareBuffer dupHardwareBuffer(const HardwareBuffer& buffer, bool doDup) {
@@ -64,7 +64,7 @@
             .handle = dupNativeHandle(buffer.handle, doDup),
     };
 
-    return std::move(dup);
+    return dup;
 }
 
 BufferDesc dupBufferDesc(const BufferDesc& src, bool doDup) {
@@ -77,7 +77,7 @@
             .metadata = src.metadata,
     };
 
-    return std::move(dup);
+    return dup;
 }
 
 bool comparePayload(const EvsEventDesc& l, const EvsEventDesc& r) {
diff --git a/automotive/ivn_android_device/impl/default/src/IvnAndroidDeviceService.cpp b/automotive/ivn_android_device/impl/default/src/IvnAndroidDeviceService.cpp
index 81f18b2..b284205 100644
--- a/automotive/ivn_android_device/impl/default/src/IvnAndroidDeviceService.cpp
+++ b/automotive/ivn_android_device/impl/default/src/IvnAndroidDeviceService.cpp
@@ -24,6 +24,7 @@
 #include <json/json.h>
 
 #include <fstream>
+#include <string>
 
 namespace android {
 namespace hardware {
@@ -48,7 +49,8 @@
 }
 
 bool IvnAndroidDeviceService::init() {
-    std::ifstream configStream(mConfigPath);
+    std::string configPathStr(mConfigPath);
+    std::ifstream configStream(configPathStr);
     if (!configStream) {
         LOG(ERROR) << "couldn't open " << mConfigPath << " for parsing.";
         return false;
diff --git a/automotive/occupant_awareness/aidl/Android.bp b/automotive/occupant_awareness/aidl/Android.bp
index 1a8124c..33406ba 100644
--- a/automotive/occupant_awareness/aidl/Android.bp
+++ b/automotive/occupant_awareness/aidl/Android.bp
@@ -14,6 +14,7 @@
         "android/hardware/automotive/occupant_awareness/*.aidl",
     ],
     stability: "vintf",
+    frozen: true,
     backend: {
         java: {
             sdk_version: "module_current",
diff --git a/automotive/remoteaccess/hal/default/Android.bp b/automotive/remoteaccess/hal/default/Android.bp
index cc8f2b0..b6c0525 100644
--- a/automotive/remoteaccess/hal/default/Android.bp
+++ b/automotive/remoteaccess/hal/default/Android.bp
@@ -51,15 +51,22 @@
 cc_binary {
     name: "android.hardware.automotive.remoteaccess@V2-default-service",
     defaults: ["remote-access-hal-defaults"],
-    vintf_fragments: ["remoteaccess-default-service.xml"],
     init_rc: ["remoteaccess-default-service.rc"],
+    vintf_fragment_modules: ["remoteaccess-default-service.xml"],
+
 }
 
 cc_binary {
     name: "android.hardware.automotive.remoteaccess@V2-tcu-test-service",
     defaults: ["remote-access-hal-defaults"],
-    vintf_fragments: ["remoteaccess-default-service.xml"],
     init_rc: ["remoteaccess-tcu-test-service.rc"],
+    vintf_fragment_modules: ["remoteaccess-default-service.xml"],
+}
+
+vintf_fragment {
+    name: "remoteaccess-default-service.xml",
+    src: "remoteaccess-default-service.xml",
+    vendor: true,
 }
 
 cc_library {
diff --git a/automotive/remoteaccess/vts/Android.bp b/automotive/remoteaccess/vts/Android.bp
index 8acd6a1..043cafa 100644
--- a/automotive/remoteaccess/vts/Android.bp
+++ b/automotive/remoteaccess/vts/Android.bp
@@ -15,6 +15,7 @@
  */
 
 package {
+    default_team: "trendy_team_aaos_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/automotive/sv/1.0/vts/functional/Android.bp b/automotive/sv/1.0/vts/functional/Android.bp
index e94893c..4ea5aff 100644
--- a/automotive/sv/1.0/vts/functional/Android.bp
+++ b/automotive/sv/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_perception_virtualization",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
@@ -45,7 +46,10 @@
         "android.hidl.memory@1.0",
         "libhidlmemory",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
     cflags: [
         "-O0",
         "-g",
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index e34e692..3d6e475 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -583,12 +583,12 @@
     while (*index < options.size()) {
         std::string option = options[*index];
         if (kSetPropOptions.find(option) != kSetPropOptions.end()) {
-            return std::move(values);
+            return values;
         }
         values.push_back(option);
         (*index)++;
     }
-    return std::move(values);
+    return values;
 }
 
 bool VehicleHalManager::parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
index 4704917..6c83339 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
@@ -16,10 +16,10 @@
 
 #define LOG_TAG "DefaultVehicleHalServer"
 
+#include <format>
 #include <fstream>
 #include <regex>
 
-#include <android-base/format.h>
 #include <android-base/logging.h>
 #include <android-base/parsedouble.h>
 #include <android-base/parseint.h>
@@ -237,7 +237,7 @@
         auto values = mServerSidePropStore.readAllValues();
         size_t i = 0;
         for (const auto& value : values) {
-            result.buffer += fmt::format("[{}]: {}\n", i, toString(value));
+            result.buffer += std::format("[{}]: {}\n", i, toString(value));
             i++;
         }
         return result;
@@ -509,7 +509,7 @@
     int64_t timestamp;
     int32_t areaId = 0;
     if (options[1] == "--setint") {
-        updatedPropValue = std::move(createVehiclePropValue(VehiclePropertyType::INT32, 1));
+        updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
         if (!android::base::ParseInt(options[3], &intValue)) {
             result.buffer += "failed to parse value as int: \"" + options[3] + "\"\n";
             result.buffer += getHelpInfo();
@@ -517,7 +517,7 @@
         }
         updatedPropValue->value.int32Values[0] = intValue;
     } else if (options[1] == "--setbool") {
-        updatedPropValue = std::move(createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1));
+        updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
         if (options[3] == "true" || options[3] == "True") {
             updatedPropValue->value.int32Values[0] = 1;
         } else if (options[3] == "false" || options[3] == "False") {
@@ -529,7 +529,7 @@
             return result;
         }
     } else {
-        updatedPropValue = std::move(createVehiclePropValue(VehiclePropertyType::FLOAT, 1));
+        updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
         if (!android::base::ParseFloat(options[3], &floatValue)) {
             result.buffer += "failed to parse value as float: \"" + options[3] + "\"\n";
             result.buffer += getHelpInfo();
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/FakeUserHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/FakeUserHal.cpp
index e9ebcc6..c735b05 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/FakeUserHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/FakeUserHal.cpp
@@ -15,6 +15,8 @@
  */
 #define LOG_TAG "FakeUserHal"
 
+#include <format>
+
 #include <cutils/log.h>
 #include <utils/SystemClock.h>
 
@@ -312,34 +314,34 @@
 }
 
 std::string FakeUserHal::showDumpHelp() {
-    return fmt::format("{}: dumps state used for user management\n", kUserHalDumpOption);
+    return std::format("{}: dumps state used for user management\n", kUserHalDumpOption);
 }
 
 std::string FakeUserHal::dump(std::string indent) {
     std::string info;
     if (mInitialUserResponseFromCmd != nullptr) {
-        info += fmt::format("{}InitialUserInfo response: {}\n", indent.c_str(),
+        info += std::format("{}InitialUserInfo response: {}\n", indent.c_str(),
                             toString(*mInitialUserResponseFromCmd).c_str());
     } else {
-        info += fmt::format("{}No InitialUserInfo response\n", indent.c_str());
+        info += std::format("{}No InitialUserInfo response\n", indent.c_str());
     }
     if (mSwitchUserResponseFromCmd != nullptr) {
-        info += fmt::format("{}SwitchUser response: {}\n", indent.c_str(),
+        info += std::format("{}SwitchUser response: {}\n", indent.c_str(),
                             toString(*mSwitchUserResponseFromCmd).c_str());
     } else {
-        info += fmt::format("{}No SwitchUser response\n", indent.c_str());
+        info += std::format("{}No SwitchUser response\n", indent.c_str());
     }
     if (mCreateUserResponseFromCmd != nullptr) {
-        info += fmt::format("{}CreateUser response: {}\n", indent.c_str(),
+        info += std::format("{}CreateUser response: {}\n", indent.c_str(),
                             toString(*mCreateUserResponseFromCmd).c_str());
     } else {
-        info += fmt::format("{}No CreateUser response\n", indent.c_str());
+        info += std::format("{}No CreateUser response\n", indent.c_str());
     }
     if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
-        info += fmt::format("{}SetUserIdentificationAssociation response: {}\n", indent.c_str(),
+        info += std::format("{}SetUserIdentificationAssociation response: {}\n", indent.c_str(),
                             toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
     } else {
-        info += fmt::format("{}No SetUserIdentificationAssociation response\n", indent.c_str());
+        info += std::format("{}No SetUserIdentificationAssociation response\n", indent.c_str());
     }
     return info;
 }
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/include/FakeUserHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/include/FakeUserHal.h
index 122aee8..33cef54 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/include/FakeUserHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/userhal/include/FakeUserHal.h
@@ -17,7 +17,6 @@
 #ifndef android_hardware_automotive_vehicle_V2_0_impl_FakeUserHal_H_
 #define android_hardware_automotive_vehicle_V2_0_impl_FakeUserHal_H_
 
-#include <android-base/format.h>
 #include <android-base/result.h>
 
 #include <android/hardware/automotive/vehicle/2.0/types.h>
diff --git a/automotive/vehicle/Android.bp b/automotive/vehicle/Android.bp
index e614937..606e108 100644
--- a/automotive/vehicle/Android.bp
+++ b/automotive/vehicle/Android.bp
@@ -22,7 +22,7 @@
     name: "VehicleHalInterfaceDefaults",
     static_libs: [
         "android.hardware.automotive.vehicle-V3-ndk",
-        "android.hardware.automotive.vehicle.property-V3-ndk",
+        "android.hardware.automotive.vehicle.property-V4-ndk",
     ],
 }
 
@@ -30,6 +30,14 @@
     name: "VehicleHalInterfaceRustDefaults",
     rustlibs: [
         "android.hardware.automotive.vehicle-V3-rust",
-        "android.hardware.automotive.vehicle.property-V3-rust",
+        "android.hardware.automotive.vehicle.property-V4-rust",
+    ],
+}
+
+aidl_interface_defaults {
+    name: "android.hardware.automotive.vehicle-latest-defaults",
+    imports: [
+        "android.hardware.automotive.vehicle-V3",
+        "android.hardware.automotive.vehicle.property-V4",
     ],
 }
diff --git a/automotive/vehicle/aidl/aidl_test/Android.bp b/automotive/vehicle/aidl/aidl_test/Android.bp
index f517df8..1e43070 100644
--- a/automotive/vehicle/aidl/aidl_test/Android.bp
+++ b/automotive/vehicle/aidl/aidl_test/Android.bp
@@ -40,7 +40,7 @@
 cc_test {
     name: "VehiclePropertyAnnotationCppTest",
     srcs: ["VehiclePropertyAnnotationCppTest.cpp"],
-    header_libs: ["IVehicleGeneratedHeaders-V3"],
+    header_libs: ["IVehicleGeneratedHeaders-V4"],
     defaults: ["VehicleHalInterfaceDefaults"],
     test_suites: ["general-tests"],
 }
@@ -49,11 +49,11 @@
     name: "VehiclePropertyAnnotationJavaTest",
     srcs: [
         "VehiclePropertyAnnotationJavaTest.java",
-        ":IVehicleGeneratedJavaFiles-V3",
+        ":IVehicleGeneratedJavaFiles-V4",
     ],
     static_libs: [
         "android.hardware.automotive.vehicle-V3-java",
-        "android.hardware.automotive.vehicle.property-V3-java",
+        "android.hardware.automotive.vehicle.property-V4-java",
         "androidx.test.runner",
         "truth",
     ],
diff --git a/automotive/vehicle/aidl/emu_metadata/android.hardware.automotive.vehicle-types-meta.json b/automotive/vehicle/aidl/emu_metadata/android.hardware.automotive.vehicle-types-meta.json
index de0e398..8ef440d 100644
--- a/automotive/vehicle/aidl/emu_metadata/android.hardware.automotive.vehicle-types-meta.json
+++ b/automotive/vehicle/aidl/emu_metadata/android.hardware.automotive.vehicle-types-meta.json
@@ -501,7 +501,7 @@
             {
                 "name": "AP_POWER_STATE_REQ",
                 "value": 289475072,
-                "description": "Property to control power state of application processor\nIt is assumed that AP's power state is controlled by a separate power controller.\nFor configuration information, VehiclePropConfig.configArray must have bit flag combining values in VehicleApPowerStateConfigFlag.\nint32Values[0] : VehicleApPowerStateReq enum value int32Values[1] : additional parameter relevant for each state, 0 if not used."
+                "description": "Property to control power state of application processor\nIt is assumed that AP's power state is controlled by a separate power controller.\nFor configuration information, VehiclePropConfig.configArray must have bit flag combining values in VehicleApPowerStateConfigFlag.\nconfigArray[0] : Bit flag combining values in VehicleApPowerStateConfigFlag, 0x0 if not used, 0x1 for enabling suspend to ram, 0x2 for supporting powering on AP from off state after timeout. 0x4 for enabling suspend to disk,\nint32Values[0] : VehicleApPowerStateReq enum value int32Values[1] : additional parameter relevant for each state, 0 if not used."
             },
             {
                 "name": "AP_POWER_STATE_REPORT",
diff --git a/automotive/vehicle/aidl/generated_lib/3/cpp/AccessForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/3/cpp/AccessForVehicleProperty.h
index 51a3025..6f6c91c 100644
--- a/automotive/vehicle/aidl/generated_lib/3/cpp/AccessForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/3/cpp/AccessForVehicleProperty.h
@@ -27,6 +27,10 @@
 #include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
 #include <aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.h>
 
+// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+#include <PerDisplayMaxBrightness.h>
+// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+
 #include <unordered_map>
 
 namespace aidl {
@@ -302,6 +306,9 @@
         {VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE, VehiclePropertyAccess::READ},
         {VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyAccess::READ_WRITE},
         {VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyAccess::READ},
+        // Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+        {PER_DISPLAY_MAX_BRIGHTNESS, VehiclePropertyAccess::READ},
+        // End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
 };
 
 }  // namespace vehicle
diff --git a/automotive/vehicle/aidl/generated_lib/3/cpp/ChangeModeForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/3/cpp/ChangeModeForVehicleProperty.h
index 60e9a72..88f2f88 100644
--- a/automotive/vehicle/aidl/generated_lib/3/cpp/ChangeModeForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/3/cpp/ChangeModeForVehicleProperty.h
@@ -27,6 +27,10 @@
 #include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
 #include <aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.h>
 
+// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+#include <PerDisplayMaxBrightness.h>
+// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+
 #include <unordered_map>
 
 namespace aidl {
@@ -302,6 +306,9 @@
         {VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE, VehiclePropertyChangeMode::ON_CHANGE},
         {VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
         {VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyChangeMode::ON_CHANGE},
+        // Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+        {PER_DISPLAY_MAX_BRIGHTNESS, VehiclePropertyChangeMode::STATIC},
+        // End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
 };
 
 }  // namespace vehicle
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/automotive/vehicle/aidl/generated_lib/3/cpp/PerDisplayMaxBrightness.h
similarity index 62%
copy from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to automotive/vehicle/aidl/generated_lib/3/cpp/PerDisplayMaxBrightness.h
index c7be950..2b50db3 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/automotive/vehicle/aidl/generated_lib/3/cpp/PerDisplayMaxBrightness.h
@@ -14,22 +14,13 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
+#pragma once
 
-import android.hardware.biometrics.fingerprint.AcquiredInfo;
+#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
 
-/**
- * @hide
- */
-@VintfStability
-union AcquiredInfoAndVendorCode {
-    /**
-     * Acquired info as specified in AcqauiredInfo.aidl
-     */
-    AcquiredInfo acquiredInfo = AcquiredInfo.UNKNOWN;
+namespace aidl::android::hardware::automotive::vehicle {
 
-    /**
-     * Vendor specific code
-     */
-    int vendorCode;
-}
+// Same as VehicleProperty::PER_DISPLAY_MAX_BRIGHTNESS as defined in v4.
+static constexpr VehicleProperty PER_DISPLAY_MAX_BRIGHTNESS = (VehicleProperty)0x11410F4E;
+
+}  // namespace aidl::android::hardware::automotive::vehicle
diff --git a/automotive/vehicle/aidl/generated_lib/3/cpp/VersionForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/3/cpp/VersionForVehicleProperty.h
index 0e80bd8..0d24273 100644
--- a/automotive/vehicle/aidl/generated_lib/3/cpp/VersionForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/3/cpp/VersionForVehicleProperty.h
@@ -26,6 +26,10 @@
 
 #include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
 
+// Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+#include <PerDisplayMaxBrightness.h>
+// End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+
 #include <unordered_map>
 
 namespace aidl {
@@ -301,6 +305,9 @@
         {VehicleProperty::CROSS_TRAFFIC_MONITORING_WARNING_STATE, 3},
         {VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, 3},
         {VehicleProperty::LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, 3},
+        // Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+        {PER_DISPLAY_MAX_BRIGHTNESS, 2},
+        // End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
 };
 
 }  // namespace vehicle
diff --git a/automotive/vehicle/aidl/generated_lib/3/java/AccessForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/3/java/AccessForVehicleProperty.java
index afb6cab..f899df8 100644
--- a/automotive/vehicle/aidl/generated_lib/3/java/AccessForVehicleProperty.java
+++ b/automotive/vehicle/aidl/generated_lib/3/java/AccessForVehicleProperty.java
@@ -28,6 +28,10 @@
 
 public final class AccessForVehicleProperty {
 
+    // Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+    private static final int PER_DISPLAY_MAX_BRIGHTNESS = 0x11410F4E;
+    // End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+
     public static final Map<Integer, Integer> values = Map.ofEntries(
         Map.entry(VehicleProperty.INFO_VIN, VehiclePropertyAccess.READ),
         Map.entry(VehicleProperty.INFO_MAKE, VehiclePropertyAccess.READ),
@@ -294,7 +298,10 @@
         Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_ENABLED, VehiclePropertyAccess.READ_WRITE),
         Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_WARNING_STATE, VehiclePropertyAccess.READ),
         Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyAccess.READ_WRITE),
-        Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyAccess.READ)
+        Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyAccess.READ),
+        // Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+        Map.entry(PER_DISPLAY_MAX_BRIGHTNESS, VehiclePropertyAccess.READ)
+        // End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
     );
 
 }
diff --git a/automotive/vehicle/aidl/generated_lib/3/java/ChangeModeForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/3/java/ChangeModeForVehicleProperty.java
index 12aff40..09989bf 100644
--- a/automotive/vehicle/aidl/generated_lib/3/java/ChangeModeForVehicleProperty.java
+++ b/automotive/vehicle/aidl/generated_lib/3/java/ChangeModeForVehicleProperty.java
@@ -28,6 +28,10 @@
 
 public final class ChangeModeForVehicleProperty {
 
+    // Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+    private static final int PER_DISPLAY_MAX_BRIGHTNESS = 0x11410F4E;
+    // End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+
     public static final Map<Integer, Integer> values = Map.ofEntries(
         Map.entry(VehicleProperty.INFO_VIN, VehiclePropertyChangeMode.STATIC),
         Map.entry(VehicleProperty.INFO_MAKE, VehiclePropertyChangeMode.STATIC),
@@ -294,7 +298,10 @@
         Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
         Map.entry(VehicleProperty.CROSS_TRAFFIC_MONITORING_WARNING_STATE, VehiclePropertyChangeMode.ON_CHANGE),
         Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
-        Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyChangeMode.ON_CHANGE)
+        Map.entry(VehicleProperty.LOW_SPEED_AUTOMATIC_EMERGENCY_BRAKING_STATE, VehiclePropertyChangeMode.ON_CHANGE),
+        // Start manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
+        Map.entry(PER_DISPLAY_MAX_BRIGHTNESS, VehiclePropertyChangeMode.STATIC)
+        // End manual edit: backport PER_DISPLAY_MAX_BRIGHTNESS.
     );
 
 }
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp
index 28c95ce..aef2909 100644
--- a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp
@@ -27,7 +27,7 @@
     defaults: ["VehicleHalDefaults"],
     static_libs: ["VehicleHalUtils"],
     header_libs: [
-        "IVehicleGeneratedHeaders-V3",
+        "IVehicleGeneratedHeaders-V4",
     ],
     shared_libs: ["libjsoncpp"],
 }
@@ -44,7 +44,7 @@
     defaults: ["VehicleHalDefaults"],
     static_libs: ["VehicleHalUtils"],
     header_libs: [
-        "IVehicleGeneratedHeaders-V3",
+        "IVehicleGeneratedHeaders-V4",
         "libbinder_headers",
     ],
     cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"],
@@ -60,7 +60,7 @@
     defaults: ["VehicleHalDefaults"],
     static_libs: ["VehicleHalUtils"],
     header_libs: [
-        "IVehicleGeneratedHeaders-V3",
+        "IVehicleGeneratedHeaders-V4",
     ],
     shared_libs: ["libjsoncpp"],
 }
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/Android.bp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/Android.bp
index abf15c5..90ea027 100644
--- a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/Android.bp
@@ -27,8 +27,6 @@
         "VehicleHalJsonConfigLoader",
         "VehicleHalUtils",
         "libgtest",
-    ],
-    shared_libs: [
         "libjsoncpp",
     ],
     defaults: ["VehicleHalDefaults"],
@@ -43,8 +41,6 @@
         "VehicleHalJsonConfigLoaderEnableTestProperties",
         "VehicleHalUtils",
         "libgtest",
-    ],
-    shared_libs: [
         "libjsoncpp",
     ],
     defaults: ["VehicleHalDefaults"],
diff --git a/automotive/vehicle/aidl/impl/default_config/TEST_MAPPING b/automotive/vehicle/aidl/impl/default_config/TEST_MAPPING
new file mode 100644
index 0000000..15ac9cb
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+    "ravenwood-presubmit": [
+        {
+            "name": "CarServiceHostUnitTest",
+            "host": true
+        }
+    ]
+}
diff --git a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
index 2d1e9ab..489d638 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
+++ b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
@@ -3195,19 +3195,22 @@
             }
         },
         {
-            "property": "VehicleProperty::DISPLAY_BRIGHTNESS",
+            "property": "VehicleProperty::PER_DISPLAY_BRIGHTNESS"
+        },
+        {
+            "property": "VehicleProperty::PER_DISPLAY_MAX_BRIGHTNESS",
             "defaultValue": {
                 "int32Values": [
+                    0,
+                    100,
+                    1,
+                    100,
+                    2,
+                    100,
+                    3,
                     100
                 ]
-            },
-            "areas": [
-                {
-                    "areaId": 0,
-                    "minInt32Value": 0,
-                    "maxInt32Value": 100
-                }
-            ]
+            }
         },
         {
             "property": "VehicleProperty::VALET_MODE_ENABLED",
diff --git a/automotive/vehicle/aidl/impl/default_config/test/Android.bp b/automotive/vehicle/aidl/impl/default_config/test/Android.bp
index 70933be..a88913e 100644
--- a/automotive/vehicle/aidl/impl/default_config/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/default_config/test/Android.bp
@@ -29,12 +29,10 @@
         "VehicleHalUtils",
         "libgmock",
         "libgtest",
+        "libjsoncpp",
     ],
     header_libs: [
-        "IVehicleGeneratedHeaders-V3",
-    ],
-    shared_libs: [
-        "libjsoncpp",
+        "IVehicleGeneratedHeaders-V4",
     ],
     data: [
         ":VehicleHalDefaultProperties_JSON",
@@ -52,15 +50,13 @@
         "VehicleHalUtils",
         "libgmock",
         "libgtest",
+        "libjsoncpp",
     ],
     cflags: [
         "-DENABLE_VEHICLE_HAL_TEST_PROPERTIES",
     ],
     header_libs: [
-        "IVehicleGeneratedHeaders-V3",
-    ],
-    shared_libs: [
-        "libjsoncpp",
+        "IVehicleGeneratedHeaders-V4",
     ],
     data: [
         ":VehicleHalDefaultProperties_JSON",
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp
index 4bc0b12..0d814ea 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp
@@ -28,8 +28,6 @@
         "VehicleHalUtils",
         "FakeVehicleHalValueGenerators",
         "FakeObd2Frame",
-    ],
-    shared_libs: [
         "libjsoncpp",
     ],
     data: [
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index ec69894..5916307 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -56,6 +56,13 @@
     FakeVehicleHardware(std::string defaultConfigDir, std::string overrideConfigDir,
                         bool forceOverride);
 
+    // s2rS2dConfig is the config for whether S2R or S2D is supported, must be a bit flag combining
+    // values from VehicleApPowerStateConfigFlag.
+    // The default implementation is reading this from system property:
+    // "ro.vendor.fake_vhal.ap_power_state_req.config".
+    FakeVehicleHardware(std::string defaultConfigDir, std::string overrideConfigDir,
+                        bool forceOverride, int32_t s2rS2dConfig);
+
     ~FakeVehicleHardware();
 
     // Get all the property configs.
@@ -193,7 +200,7 @@
     // provides power controlling related properties.
     std::string mPowerControllerServiceAddress = "";
 
-    void init();
+    void init(int32_t s2rS2dConfig);
     // Stores the initial value to property store.
     void storePropInitialValue(const ConfigDeclaration& config);
     // The callback that would be called when a vehicle property value change happens.
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 54dcca2..a6247a7 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -348,6 +348,13 @@
 
 FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir,
                                          std::string overrideConfigDir, bool forceOverride)
+    : FakeVehicleHardware(defaultConfigDir, overrideConfigDir, forceOverride,
+                          /*s2rS2dConfig=*/
+                          GetIntProperty(POWER_STATE_REQ_CONFIG_PROPERTY, /*default_value=*/0)) {}
+
+FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir,
+                                         std::string overrideConfigDir, bool forceOverride,
+                                         int32_t s2rS2dConfig)
     : mValuePool(std::make_unique<VehiclePropValuePool>()),
       mServerSidePropStore(new VehiclePropertyStore(mValuePool)),
       mDefaultConfigDir(defaultConfigDir),
@@ -360,7 +367,7 @@
       mPendingGetValueRequests(this),
       mPendingSetValueRequests(this),
       mForceOverride(forceOverride) {
-    init();
+    init(s2rS2dConfig);
 }
 
 FakeVehicleHardware::~FakeVehicleHardware() {
@@ -388,7 +395,7 @@
     return configsByPropId;
 }
 
-void FakeVehicleHardware::init() {
+void FakeVehicleHardware::init(int32_t s2rS2dConfig) {
     maybeGetGrpcServiceInfo(&mPowerControllerServiceAddress);
 
     for (auto& [_, configDeclaration] : loadConfigDeclarations()) {
@@ -396,8 +403,7 @@
         VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
 
         if (cfg.prop == toInt(VehicleProperty::AP_POWER_STATE_REQ)) {
-            int config = GetIntProperty(POWER_STATE_REQ_CONFIG_PROPERTY, /*default_value=*/0);
-            cfg.configArray[0] = config;
+            cfg.configArray[0] = s2rS2dConfig;
         } else if (cfg.prop == OBD2_FREEZE_FRAME) {
             tokenFunction = [](const VehiclePropValue& propValue) { return propValue.timestamp; };
         }
@@ -532,6 +538,9 @@
                        << getErrorMsg(writeResult);
             }
             break;
+        case toInt(VehicleApPowerStateReport::ON):
+            ALOGI("Received VehicleApPowerStateReport::ON, entering normal operating state");
+            break;
         default:
             ALOGE("Unknown VehicleApPowerStateReport: %d", state);
             break;
@@ -1047,6 +1056,10 @@
     VhalResult<void> isAdasPropertyAvailableResult;
     VhalResult<bool> isCruiseControlTypeStandardResult;
     switch (propId) {
+        case toInt(VehicleProperty::DISPLAY_BRIGHTNESS):
+        case toInt(VehicleProperty::PER_DISPLAY_BRIGHTNESS):
+            ALOGD("DISPLAY_BRIGHTNESS: %s", value.toString().c_str());
+            return {};
         case toInt(VehicleProperty::AP_POWER_STATE_REPORT):
             *isSpecialValue = true;
             return setApPowerStateReport(value);
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
index 9f002dd..62c1147 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
@@ -40,10 +40,10 @@
         "FakeUserHal",
         "libgtest",
         "libgmock",
+        "libjsoncpp",
     ],
     shared_libs: [
         "libgrpc++",
-        "libjsoncpp",
         "libprotobuf-cpp-full",
     ],
     data: [
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index 8dbba19..f6098ca 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -20,6 +20,7 @@
 #include <FakeUserHal.h>
 #include <PropertyUtils.h>
 
+#include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateConfigFlag.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.h>
 #include <android/hardware/automotive/vehicle/TestVendorProperty.h>
 
@@ -73,6 +74,7 @@
 using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
+using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateConfigFlag;
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateShutdownParam;
@@ -1871,7 +1873,7 @@
 
 TEST_F(FakeVehicleHardwareTest, testGetHvacPropNotAvailable) {
     FakeVehicleHardwareTestHelper helper(getHardware());
-    auto hvacPowerOnConfig = std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON)));
+    auto hvacPowerOnConfig = getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON));
     EXPECT_NE(hvacPowerOnConfig, nullptr);
     for (auto& hvacPowerOnAreaConfig : hvacPowerOnConfig->areaConfigs) {
         int hvacPowerAreaId = hvacPowerOnAreaConfig.areaId;
@@ -1882,7 +1884,7 @@
         EXPECT_EQ(status, StatusCode::OK);
 
         for (auto& powerPropId : helper.getHvacPowerDependentProps()) {
-            auto powerPropConfig = std::move(getVehiclePropConfig(powerPropId));
+            auto powerPropConfig = getVehiclePropConfig(powerPropId);
             EXPECT_NE(powerPropConfig, nullptr);
             if (powerPropConfig->access == VehiclePropertyAccess::WRITE) {
                 continue;
@@ -1918,7 +1920,7 @@
 
 TEST_F(FakeVehicleHardwareTest, testSetHvacPropNotAvailable) {
     FakeVehicleHardwareTestHelper helper(getHardware());
-    auto hvacPowerOnConfig = std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON)));
+    auto hvacPowerOnConfig = getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON));
     EXPECT_NE(hvacPowerOnConfig, nullptr);
     for (auto& hvacPowerOnAreaConfig : hvacPowerOnConfig->areaConfigs) {
         int hvacPowerAreaId = hvacPowerOnAreaConfig.areaId;
@@ -1929,7 +1931,7 @@
         EXPECT_EQ(status, StatusCode::OK);
 
         for (auto& powerPropId : helper.getHvacPowerDependentProps()) {
-            auto powerPropConfig = std::move(getVehiclePropConfig(powerPropId));
+            auto powerPropConfig = getVehiclePropConfig(powerPropId);
             EXPECT_NE(powerPropConfig, nullptr);
             if (powerPropConfig->access == VehiclePropertyAccess::READ) {
                 continue;
@@ -1968,7 +1970,7 @@
 
 TEST_F(FakeVehicleHardwareTest, testHvacPowerOnSendCurrentHvacPropValues) {
     FakeVehicleHardwareTestHelper helper(getHardware());
-    auto hvacPowerOnConfig = std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON)));
+    auto hvacPowerOnConfig = getVehiclePropConfig(toInt(VehicleProperty::HVAC_POWER_ON));
     EXPECT_NE(hvacPowerOnConfig, nullptr);
     for (auto& hvacPowerOnAreaConfig : hvacPowerOnConfig->areaConfigs) {
         int hvacPowerAreaId = hvacPowerOnAreaConfig.areaId;
@@ -2007,9 +2009,9 @@
 }
 
 TEST_F(FakeVehicleHardwareTest, testHvacDualOnSynchronizesTemp) {
-    auto hvacDualOnConfig = std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_DUAL_ON)));
+    auto hvacDualOnConfig = getVehiclePropConfig(toInt(VehicleProperty::HVAC_DUAL_ON));
     auto hvacTemperatureSetConfig =
-            std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET)));
+            getVehiclePropConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
     EXPECT_NE(hvacDualOnConfig, nullptr);
     EXPECT_NE(hvacTemperatureSetConfig, nullptr);
     for (auto& hvacTemperatureSetConfig : hvacTemperatureSetConfig->areaConfigs) {
@@ -3605,7 +3607,7 @@
     // Config array values from HVAC_TEMPERATURE_SET in DefaultProperties.json
     auto configs = getHardware()->getAllPropertyConfigs();
     auto hvacTemperatureSetConfig =
-            std::move(getVehiclePropConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET)));
+            getVehiclePropConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
     EXPECT_NE(hvacTemperatureSetConfig, nullptr);
 
     auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfig->configArray;
@@ -3863,6 +3865,25 @@
     }
 }
 
+TEST_F(FakeVehicleHardwareTest, testOverrideApPowerStateReqConfig) {
+    auto hardware = std::make_unique<FakeVehicleHardware>(
+            android::base::GetExecutableDirectory(),
+            /*overrideConfigDir=*/"",
+            /*forceOverride=*/false,
+            toInt(VehicleApPowerStateConfigFlag::ENABLE_DEEP_SLEEP_FLAG) |
+                    toInt(VehicleApPowerStateConfigFlag::ENABLE_HIBERNATION_FLAG));
+
+    std::vector<VehiclePropConfig> configs = hardware->getAllPropertyConfigs();
+
+    for (const auto& config : configs) {
+        if (config.prop != toInt(VehicleProperty::AP_POWER_STATE_REQ)) {
+            continue;
+        }
+        ASSERT_EQ(config.configArray[0], 0x5);
+        break;
+    }
+}
+
 }  // namespace fake
 }  // namespace vehicle
 }  // namespace automotive
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
index fcbe8fd..1bf5ce1 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
@@ -17,7 +17,6 @@
 #ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_FakeUserHal_H_
 #define android_hardware_automotive_vehicle_aidl_impl_fake_impl_userhal_include_FakeUserHal_H_
 
-#include <android-base/format.h>
 #include <android-base/result.h>
 #include <android-base/thread_annotations.h>
 
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp b/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
index 878c2e7..309dd5f 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
@@ -19,6 +19,8 @@
 
 #include "UserHalHelper.h"
 
+#include <format>
+
 #include <VehicleUtils.h>
 #include <utils/Log.h>
 #include <utils/SystemClock.h>
@@ -336,7 +338,7 @@
 }
 
 std::string FakeUserHal::showDumpHelp() const {
-    return fmt::format("{}: dumps state used for user management\n", kUserHalDumpOption);
+    return std::format("{}: dumps state used for user management\n", kUserHalDumpOption);
 }
 
 std::string FakeUserHal::dump() const {
@@ -344,23 +346,23 @@
 
     std::string info;
     if (mInitialUserResponseFromCmd != nullptr) {
-        info += fmt::format("InitialUserInfo response: {}\n",
+        info += std::format("InitialUserInfo response: {}\n",
                             mInitialUserResponseFromCmd->toString());
     } else {
         info += "No InitialUserInfo response\n";
     }
     if (mSwitchUserResponseFromCmd != nullptr) {
-        info += fmt::format("SwitchUser response: {}\n", mSwitchUserResponseFromCmd->toString());
+        info += std::format("SwitchUser response: {}\n", mSwitchUserResponseFromCmd->toString());
     } else {
         info += "No SwitchUser response\n";
     }
     if (mCreateUserResponseFromCmd != nullptr) {
-        info += fmt::format("CreateUser response: {}\n", mCreateUserResponseFromCmd->toString());
+        info += std::format("CreateUser response: {}\n", mCreateUserResponseFromCmd->toString());
     } else {
         info += "No CreateUser response\n";
     }
     if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
-        info += fmt::format("SetUserIdentificationAssociation response: {}\n",
+        info += std::format("SetUserIdentificationAssociation response: {}\n",
                             mSetUserIdentificationAssociationResponseFromCmd->toString());
     } else {
         info += "No SetUserIdentificationAssociation response\n";
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
index 73bb521..8750375 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
@@ -83,6 +83,17 @@
     return configs;
 }
 
+std::optional<aidlvhal::VehiclePropConfig> GRPCVehicleHardware::getPropertyConfig(
+        int32_t propId) const {
+    // TODO(b/354055835): Use GRPC call to get one config instead of getting all the configs.
+    for (const auto& config : getAllPropertyConfigs()) {
+        if (config.prop == propId) {
+            return config;
+        }
+    }
+    return std::nullopt;
+}
+
 aidlvhal::StatusCode GRPCVehicleHardware::setValues(
         std::shared_ptr<const SetValuesCallback> callback,
         const std::vector<aidlvhal::SetValueRequest>& requests) {
@@ -265,6 +276,7 @@
     return {
             .callerShouldDumpState = protoDumpResult.caller_should_dump_state(),
             .buffer = protoDumpResult.buffer(),
+            .refreshPropertyConfigs = protoDumpResult.refresh_property_configs(),
     };
 }
 
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
index 1edf658..15f473c 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
@@ -50,6 +50,10 @@
     // Get all the property configs.
     std::vector<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const override;
 
+    // Get the config for the specified propId.
+    std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+    getPropertyConfig(int32_t propId) const override;
+
     // Set property values asynchronously. Server could return before the property set requests
     // are sent to vehicle bus or before property set confirmation is received. The callback is
     // safe to be called after the function returns and is safe to be called in a different thread.
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
index d7cbe1b..7697c03 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
@@ -226,6 +226,7 @@
     auto dumpResult = mHardware->dump(dumpOptionStrings);
     result->set_caller_should_dump_state(dumpResult.callerShouldDumpState);
     result->set_buffer(dumpResult.buffer);
+    result->set_refresh_property_configs(dumpResult.refreshPropertyConfigs);
     return ::grpc::Status::OK;
 }
 
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
index 2efda5b..6fe40a6 100644
--- a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <format>
 #include <vector>
 
 #include <JsonConfigLoader.h>
@@ -21,7 +22,6 @@
 #include <VehicleHalTypes.h>
 
 #include <android-base/file.h>
-#include <android-base/format.h>
 #include <android/hardware/automotive/vehicle/SubscribeOptions.pb.h>
 #include <android/hardware/automotive/vehicle/VehiclePropConfig.pb.h>
 #include <android/hardware/automotive/vehicle/VehiclePropValue.pb.h>
@@ -106,13 +106,13 @@
 INSTANTIATE_TEST_SUITE_P(DefaultConfigs, PropConfigConversionTest,
                          ::testing::ValuesIn(prepareTestConfigs()),
                          [](const ::testing::TestParamInfo<aidl_vehicle::VehiclePropConfig>& info) {
-                             return ::fmt::format("property_{:d}", info.param.prop);
+                             return ::std::format("property_{:d}", info.param.prop);
                          });
 
 INSTANTIATE_TEST_SUITE_P(TestValues, PropValueConversionTest,
                          ::testing::ValuesIn(prepareTestValues()),
                          [](const ::testing::TestParamInfo<aidl_vehicle::VehiclePropValue>& info) {
-                             return ::fmt::format("property_{:d}", info.param.prop);
+                             return ::std::format("property_{:d}", info.param.prop);
                          });
 
 TEST_F(PropValueConversionTest, testConvertSubscribeOption) {
diff --git a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
index f49d91b..0684655 100644
--- a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
@@ -20,6 +20,7 @@
 #include <VehicleHalTypes.h>
 
 #include <memory>
+#include <optional>
 #include <vector>
 
 namespace android {
@@ -46,33 +47,53 @@
     int32_t areaId;
 };
 
+namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
+
 // An abstract interface to access vehicle hardware.
 // For virtualized VHAL, GrpcVehicleHardware would communicate with a VehicleHardware
 // implementation in another VM through GRPC. For non-virtualzied VHAL, VHAL directly communicates
 // with a VehicleHardware through this interface.
 class IVehicleHardware {
   public:
-    using SetValuesCallback = std::function<void(
-            std::vector<aidl::android::hardware::automotive::vehicle::SetValueResult>)>;
-    using GetValuesCallback = std::function<void(
-            std::vector<aidl::android::hardware::automotive::vehicle::GetValueResult>)>;
-    using PropertyChangeCallback = std::function<void(
-            std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>)>;
+    using SetValuesCallback = std::function<void(std::vector<aidlvhal::SetValueResult>)>;
+    using GetValuesCallback = std::function<void(std::vector<aidlvhal::GetValueResult>)>;
+    using PropertyChangeCallback = std::function<void(std::vector<aidlvhal::VehiclePropValue>)>;
     using PropertySetErrorCallback = std::function<void(std::vector<SetValueErrorEvent>)>;
 
     virtual ~IVehicleHardware() = default;
 
     // Get all the property configs.
-    virtual std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
-    getAllPropertyConfigs() const = 0;
+    virtual std::vector<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const = 0;
+
+    // Get the property configs for the specified propId. This is used for early-boot
+    // native VHAL clients to access certain property configs when not all property configs are
+    // available. For example, a config discovery process might be required to determine the
+    // property config for HVAC. However, for early boot properties, e.g. VHAL_HEARTBEAT, it
+    // could return before the config discovery process.
+    //
+    // Currently Android system may try to access the following properties during early boot:
+    // STORAGE_ENCRYPTION_BINDING_SEED, WATCHDOG_ALIVE, WATCHDOG_TERMINATE_PROCESS, VHAL_HEARTBEAT,
+    // CURRENT_POWER_POLICY, POWER_POLICY_REQ, POWER_POLICY_GROUP_REQ. They should return
+    // quickly otherwise the whole bootup process might be blocked.
+    virtual std::optional<aidlvhal::VehiclePropConfig> getPropertyConfig(int32_t propId) const {
+        // The default implementation is to use getAllPropertyConfigs(). This should be
+        // overridden if getAllPropertyConfigs() takes a while to return for initial boot or
+        // relies on ethernet or other communication channel that is not available during early
+        // boot.
+        for (const auto& config : getAllPropertyConfigs()) {
+            if (config.prop == propId) {
+                return config;
+            }
+        }
+        return std::nullopt;
+    }
 
     // Set property values asynchronously. Server could return before the property set requests
     // are sent to vehicle bus or before property set confirmation is received. The callback is
     // safe to be called after the function returns and is safe to be called in a different thread.
-    virtual aidl::android::hardware::automotive::vehicle::StatusCode setValues(
+    virtual aidlvhal::StatusCode setValues(
             std::shared_ptr<const SetValuesCallback> callback,
-            const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
-                    requests) = 0;
+            const std::vector<aidlvhal::SetValueRequest>& requests) = 0;
 
     // Get property values asynchronously. Server could return before the property values are ready.
     // The callback is safe to be called after the function returns and is safe to be called in a
@@ -86,7 +107,7 @@
     virtual DumpResult dump(const std::vector<std::string>& options) = 0;
 
     // Check whether the system is healthy, return {@code StatusCode::OK} for healthy.
-    virtual aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() = 0;
+    virtual aidlvhal::StatusCode checkHealth() = 0;
 
     // Register a callback that would be called when there is a property change event from vehicle.
     // This function must only be called once during initialization.
@@ -179,16 +200,14 @@
     // 5. The second subscriber is removed, 'unsubscribe' is called.
     //    The impl can optionally disable the polling for vehicle speed.
     //
-    virtual aidl::android::hardware::automotive::vehicle::StatusCode subscribe(
-            [[maybe_unused]] aidl::android::hardware::automotive::vehicle::SubscribeOptions
-                    options) {
-        return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+    virtual aidlvhal::StatusCode subscribe([[maybe_unused]] aidlvhal::SubscribeOptions options) {
+        return aidlvhal::StatusCode::OK;
     }
 
     // A [propId, areaId] is unsubscribed. This applies for both continuous or on-change property.
-    virtual aidl::android::hardware::automotive::vehicle::StatusCode unsubscribe(
-            [[maybe_unused]] int32_t propId, [[maybe_unused]] int32_t areaId) {
-        return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+    virtual aidlvhal::StatusCode unsubscribe([[maybe_unused]] int32_t propId,
+                                             [[maybe_unused]] int32_t areaId) {
+        return aidlvhal::StatusCode::OK;
     }
 
     // This function is deprecated, subscribe/unsubscribe should be used instead.
@@ -216,10 +235,10 @@
     //
     // If the impl is always polling at {@code maxSampleRate} as specified in config, then this
     // function can be a no-op.
-    virtual aidl::android::hardware::automotive::vehicle::StatusCode updateSampleRate(
-            [[maybe_unused]] int32_t propId, [[maybe_unused]] int32_t areaId,
-            [[maybe_unused]] float sampleRate) {
-        return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+    virtual aidlvhal::StatusCode updateSampleRate([[maybe_unused]] int32_t propId,
+                                                  [[maybe_unused]] int32_t areaId,
+                                                  [[maybe_unused]] float sampleRate) {
+        return aidlvhal::StatusCode::OK;
     }
 };
 
diff --git a/automotive/vehicle/aidl/impl/proto/Android.bp b/automotive/vehicle/aidl/impl/proto/Android.bp
index b2edf75..0d3df49 100644
--- a/automotive/vehicle/aidl/impl/proto/Android.bp
+++ b/automotive/vehicle/aidl/impl/proto/Android.bp
@@ -106,3 +106,21 @@
         "-Wno-unused-parameter",
     ],
 }
+
+rust_protobuf {
+    name: "libvehicle_hal_property_protos",
+    crate_name: "vehicle_hal_property_protos",
+    protos: [":VehicleHalProtoFiles"],
+    source_stem: "vehicle_hal_property_protos",
+    host_supported: true,
+    vendor_available: true,
+    product_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    exported_include_dirs: ["."],
+    proto_flags: [
+        "-I external/protobuf/src",
+    ],
+}
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpResult.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpResult.proto
index 25bb7d4..fbfb505 100644
--- a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpResult.proto
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpResult.proto
@@ -25,4 +25,6 @@
     bool caller_should_dump_state = 1;
     /* The dumped information for the caller to print. */
     string buffer = 2;
+    /* To pass if DefaultVehicleHal should refresh the property configs. */
+    bool refresh_property_configs = 3;
 }
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index 90a7c46..2bb4ba8 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -17,9 +17,10 @@
 #ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
 #define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
 
+#include <format>
+
 #include <VehicleHalTypes.h>
 
-#include <android-base/format.h>
 #include <android-base/result.h>
 #include <math/HashCombine.h>
 #include <utils/Log.h>
@@ -289,7 +290,7 @@
     }
     return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
             toInt(status),
-            fmt::format("{}, error: {}", additionalErrorMsg, getErrorMsg(result)).c_str());
+            std::format("{}, error: {}", additionalErrorMsg, getErrorMsg(result)).c_str());
 }
 
 template <class T, class E>
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
index a7caeb1..c3a46c6 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
@@ -289,7 +289,7 @@
 
     for (auto const& [_, record] : mRecordsByPropId) {
         for (auto const& [_, value] : record.values) {
-            allValues.push_back(std::move(mValuePool->obtain(*value)));
+            allValues.push_back(mValuePool->obtain(*value));
         }
     }
 
@@ -308,7 +308,7 @@
     }
 
     for (auto const& [_, value] : record->values) {
-        values.push_back(std::move(mValuePool->obtain(*value)));
+        values.push_back(mValuePool->obtain(*value));
     }
     return values;
 }
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/PendingRequestPoolTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/PendingRequestPoolTest.cpp
index 734c739..cc690d7 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/PendingRequestPoolTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/PendingRequestPoolTest.cpp
@@ -57,7 +57,7 @@
 
   private:
     // Test timeout is 0.1s.
-    static const int64_t TEST_TIMEOUT = 100000000;
+    static constexpr int64_t TEST_TIMEOUT = 100000000;
 
     std::unique_ptr<PendingRequestPool> mPool;
 };
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
index 6646b7e..22f5c73 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
@@ -328,7 +328,7 @@
 TEST_F(VehiclePropertyStoreTest, testRemoveValuesForProperty) {
     auto values = getTestPropValues();
     for (const auto& value : values) {
-        ASSERT_RESULT_OK(mStore->writeValue(std::move(mValuePool->obtain(value))));
+        ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
     }
 
     mStore->removeValuesForProperty(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
diff --git a/automotive/vehicle/aidl/impl/vhal/Android.bp b/automotive/vehicle/aidl/impl/vhal/Android.bp
index 5cc071d..54d148e 100644
--- a/automotive/vehicle/aidl/impl/vhal/Android.bp
+++ b/automotive/vehicle/aidl/impl/vhal/Android.bp
@@ -66,7 +66,7 @@
     ],
     header_libs: [
         "IVehicleHardware",
-        "IVehicleGeneratedHeaders-V3",
+        "IVehicleGeneratedHeaders-V4",
     ],
     shared_libs: [
         "libbinder_ndk",
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index fa2a310..932a2e2 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -31,6 +31,7 @@
 #include <android-base/thread_annotations.h>
 #include <android/binder_auto_utils.h>
 
+#include <functional>
 #include <memory>
 #include <mutex>
 #include <shared_mutex>
@@ -138,12 +139,11 @@
     // Only used for testing.
     int32_t mTestInterfaceVersion = 0;
 
-    // mConfigsByPropId and mConfigFile is lazy initialized.
-    mutable std::mutex mConfigInitLock;
-    mutable bool mConfigInit GUARDED_BY(mConfigInitLock) = false;
+    mutable std::atomic<bool> mConfigInit = false;
+    mutable std::shared_timed_mutex mConfigLock;
     mutable std::unordered_map<int32_t, aidlvhal::VehiclePropConfig> mConfigsByPropId
-            GUARDED_BY(mConfigInitLock);
-    mutable std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile GUARDED_BY(mConfigInitLock);
+            GUARDED_BY(mConfigLock);
+    mutable std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile GUARDED_BY(mConfigLock);
 
     std::mutex mLock;
     std::unordered_map<const AIBinder*, std::unique_ptr<OnBinderDiedContext>> mOnBinderDiedContexts
@@ -175,7 +175,10 @@
 
     android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
             const std::vector<aidlvhal::SetValueRequest>& requests);
-    VhalResult<void> checkSubscribeOptions(const std::vector<aidlvhal::SubscribeOptions>& options);
+    VhalResult<void> checkSubscribeOptions(
+            const std::vector<aidlvhal::SubscribeOptions>& options,
+            const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& configsByPropId)
+            REQUIRES_SHARED(mConfigLock);
 
     VhalResult<void> checkPermissionHelper(const aidlvhal::VehiclePropValue& value,
                                            aidlvhal::VehiclePropertyAccess accessToTest) const;
@@ -184,7 +187,7 @@
 
     VhalResult<void> checkWritePermission(const aidlvhal::VehiclePropValue& value) const;
 
-    android::base::Result<const aidlvhal::VehiclePropConfig*> getConfig(int32_t propId) const;
+    android::base::Result<aidlvhal::VehiclePropConfig> getConfig(int32_t propId) const;
 
     void onBinderDiedWithContext(const AIBinder* clientId);
 
@@ -196,7 +199,9 @@
 
     bool checkDumpPermission();
 
-    bool getAllPropConfigsFromHardwareLocked() const REQUIRES(mConfigInitLock);
+    bool isConfigSupportedForCurrentVhalVersion(const aidlvhal::VehiclePropConfig& config) const;
+
+    bool getAllPropConfigsFromHardwareLocked() const EXCLUDES(mConfigLock);
 
     // The looping handler function to process all onBinderDied or onBinderUnlinked events in
     // mBinderEvents.
@@ -209,10 +214,12 @@
 
     int32_t getVhalInterfaceVersion() const;
 
-    // Gets mConfigsByPropId, lazy init it if necessary.
-    const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& getConfigsByPropId() const;
-    // Gets mConfigFile, lazy init it if necessary.
-    const ndk::ScopedFileDescriptor* getConfigFile() const;
+    // Gets mConfigsByPropId, lazy init it if necessary. Note that the reference is only valid in
+    // the scope of the callback and it is guaranteed that read lock is obtained during the
+    // callback.
+    void getConfigsByPropId(
+            std::function<void(const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>&)>
+                    callback) const EXCLUDES(mConfigLock);
 
     // Puts the property change events into a queue so that they can handled in batch.
     static void batchPropertyChangeEvent(
@@ -239,6 +246,12 @@
 
     static void onBinderUnlinked(void* cookie);
 
+    static void parseSubscribeOptions(
+            const std::vector<aidlvhal::SubscribeOptions>& options,
+            const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& configsByPropId,
+            std::vector<aidlvhal::SubscribeOptions>& onChangeSubscriptions,
+            std::vector<aidlvhal::SubscribeOptions>& continuousSubscriptions);
+
     // Test-only
     // Set the default timeout for pending requests.
     void setTimeout(int64_t timeoutInNano);
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index 9dc039d..0ead819 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -95,6 +95,18 @@
     return sampleRateHz;
 }
 
+class SCOPED_CAPABILITY SharedScopedLockAssertion {
+  public:
+    SharedScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE_SHARED(mutex) {}
+    ~SharedScopedLockAssertion() RELEASE() {}
+};
+
+class SCOPED_CAPABILITY UniqueScopedLockAssertion {
+  public:
+    UniqueScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE(mutex) {}
+    ~UniqueScopedLockAssertion() RELEASE() {}
+};
+
 }  // namespace
 
 DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
@@ -328,95 +340,127 @@
     return myVersion;
 }
 
-bool DefaultVehicleHal::getAllPropConfigsFromHardwareLocked() const {
-    ALOGD("Get all property configs from hardware");
-    auto configs = mVehicleHardware->getAllPropertyConfigs();
-    std::vector<VehiclePropConfig> filteredConfigs;
+bool DefaultVehicleHal::isConfigSupportedForCurrentVhalVersion(
+        const VehiclePropConfig& config) const {
     int32_t myVersion = getVhalInterfaceVersion();
-    for (auto& config : configs) {
-        if (!isSystemProp(config.prop)) {
-            filteredConfigs.push_back(std::move(config));
-            continue;
-        }
-        VehicleProperty property = static_cast<VehicleProperty>(config.prop);
-        std::string propertyName = aidl::android::hardware::automotive::vehicle::toString(property);
-        auto it = VersionForVehicleProperty.find(property);
-        if (it == VersionForVehicleProperty.end()) {
-            ALOGE("The property: %s is not a supported system property, ignore",
-                  propertyName.c_str());
-            continue;
-        }
-        int requiredVersion = it->second;
-        if (myVersion < requiredVersion) {
-            ALOGE("The property: %s is not supported for current client VHAL version, "
-                  "require %d, current version: %d, ignore",
-                  propertyName.c_str(), requiredVersion, myVersion);
-            continue;
-        }
-        filteredConfigs.push_back(std::move(config));
+    if (!isSystemProp(config.prop)) {
+        return true;
     }
-    for (auto& config : filteredConfigs) {
-        mConfigsByPropId[config.prop] = config;
-    }
-    VehiclePropConfigs vehiclePropConfigs;
-    vehiclePropConfigs.payloads = std::move(filteredConfigs);
-    auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
-    if (!result.ok()) {
-        ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
-              result.error().message().c_str(), static_cast<int>(result.error().code()));
-        mConfigFile = nullptr;
+    VehicleProperty property = static_cast<VehicleProperty>(config.prop);
+    std::string propertyName = aidl::android::hardware::automotive::vehicle::toString(property);
+    auto it = VersionForVehicleProperty.find(property);
+    if (it == VersionForVehicleProperty.end()) {
+        ALOGE("The property: %s is not a supported system property, ignore", propertyName.c_str());
         return false;
     }
-
-    if (result.value() != nullptr) {
-        mConfigFile = std::move(result.value());
+    int requiredVersion = it->second;
+    if (myVersion < requiredVersion) {
+        ALOGE("The property: %s is not supported for current client VHAL version, "
+              "require %d, current version: %d, ignore",
+              propertyName.c_str(), requiredVersion, myVersion);
+        return false;
     }
     return true;
 }
 
-const ScopedFileDescriptor* DefaultVehicleHal::getConfigFile() const {
-    std::scoped_lock lockGuard(mConfigInitLock);
-    if (!mConfigInit) {
-        CHECK(getAllPropConfigsFromHardwareLocked())
-                << "Failed to get property configs from hardware";
-        mConfigInit = true;
+bool DefaultVehicleHal::getAllPropConfigsFromHardwareLocked() const {
+    ALOGD("Get all property configs from hardware");
+    auto configs = mVehicleHardware->getAllPropertyConfigs();
+    std::vector<VehiclePropConfig> filteredConfigs;
+    for (const auto& config : configs) {
+        if (isConfigSupportedForCurrentVhalVersion(config)) {
+            filteredConfigs.push_back(std::move(config));
+        }
     }
-    return mConfigFile.get();
+
+    {
+        std::unique_lock<std::shared_timed_mutex> configWriteLock(mConfigLock);
+        UniqueScopedLockAssertion lockAssertion(mConfigLock);
+
+        for (auto& config : filteredConfigs) {
+            mConfigsByPropId[config.prop] = config;
+        }
+        VehiclePropConfigs vehiclePropConfigs;
+        vehiclePropConfigs.payloads = std::move(filteredConfigs);
+        auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
+        if (!result.ok()) {
+            ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
+                  result.error().message().c_str(), static_cast<int>(result.error().code()));
+            mConfigFile = nullptr;
+            return false;
+        }
+
+        if (result.value() != nullptr) {
+            mConfigFile = std::move(result.value());
+        }
+    }
+
+    mConfigInit = true;
+    return true;
 }
 
-const std::unordered_map<int32_t, VehiclePropConfig>& DefaultVehicleHal::getConfigsByPropId()
-        const {
-    std::scoped_lock lockGuard(mConfigInitLock);
+void DefaultVehicleHal::getConfigsByPropId(
+        std::function<void(const std::unordered_map<int32_t, VehiclePropConfig>&)> callback) const {
     if (!mConfigInit) {
         CHECK(getAllPropConfigsFromHardwareLocked())
                 << "Failed to get property configs from hardware";
-        mConfigInit = true;
     }
-    return mConfigsByPropId;
+
+    std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
+    SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+    callback(mConfigsByPropId);
 }
 
 ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
-    const ScopedFileDescriptor* configFile = getConfigFile();
-    const auto& configsByPropId = getConfigsByPropId();
-    if (configFile != nullptr) {
+    if (!mConfigInit) {
+        CHECK(getAllPropConfigsFromHardwareLocked())
+                << "Failed to get property configs from hardware";
+    }
+
+    std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
+    SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+    if (mConfigFile != nullptr) {
         output->payloads.clear();
-        output->sharedMemoryFd.set(dup(configFile->get()));
+        output->sharedMemoryFd.set(dup(mConfigFile->get()));
         return ScopedAStatus::ok();
     }
-    output->payloads.reserve(configsByPropId.size());
-    for (const auto& [_, config] : configsByPropId) {
+
+    output->payloads.reserve(mConfigsByPropId.size());
+    for (const auto& [_, config] : mConfigsByPropId) {
         output->payloads.push_back(config);
     }
     return ScopedAStatus::ok();
 }
 
-Result<const VehiclePropConfig*> DefaultVehicleHal::getConfig(int32_t propId) const {
-    const auto& configsByPropId = getConfigsByPropId();
-    auto it = configsByPropId.find(propId);
-    if (it == configsByPropId.end()) {
-        return Error() << "no config for property, ID: " << propId;
+Result<VehiclePropConfig> DefaultVehicleHal::getConfig(int32_t propId) const {
+    Result<VehiclePropConfig> result;
+
+    if (!mConfigInit) {
+        std::optional<VehiclePropConfig> config = mVehicleHardware->getPropertyConfig(propId);
+        if (!config.has_value()) {
+            return Error() << "no config for property, ID: " << propId;
+        }
+        if (!isConfigSupportedForCurrentVhalVersion(config.value())) {
+            return Error() << "property not supported for current VHAL interface, ID: " << propId;
+        }
+
+        return config.value();
     }
-    return &(it->second);
+
+    getConfigsByPropId([this, &result, propId](const auto& configsByPropId) {
+        SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+        auto it = configsByPropId.find(propId);
+        if (it == configsByPropId.end()) {
+            result = Error() << "no config for property, ID: " << propId;
+            return;
+        }
+        // Copy the VehiclePropConfig
+        result = it->second;
+    });
+    return result;
 }
 
 Result<void> DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) {
@@ -425,15 +469,15 @@
     if (!result.ok()) {
         return result.error();
     }
-    const VehiclePropConfig* config = result.value();
-    const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, *config);
+    const VehiclePropConfig& config = result.value();
+    const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, config);
     if (!isGlobalProp(propId) && areaConfig == nullptr) {
         // Ignore areaId for global property. For non global property, check whether areaId is
         // allowed. areaId must appear in areaConfig.
         return Error() << "invalid area ID: " << propValue.areaId << " for prop ID: " << propId
                        << ", not listed in config";
     }
-    if (auto result = checkPropValue(propValue, config); !result.ok()) {
+    if (auto result = checkPropValue(propValue, &config); !result.ok()) {
         return Error() << "invalid property value: " << propValue.toString()
                        << ", error: " << getErrorMsg(result);
     }
@@ -659,17 +703,43 @@
 ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
                                                 VehiclePropConfigs* output) {
     std::vector<VehiclePropConfig> configs;
-    const auto& configsByPropId = getConfigsByPropId();
-    for (int32_t prop : props) {
-        auto it = configsByPropId.find(prop);
-        if (it != configsByPropId.end()) {
-            configs.push_back(it->second);
-        } else {
-            return ScopedAStatus::fromServiceSpecificErrorWithMessage(
-                    toInt(StatusCode::INVALID_ARG),
-                    StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
+
+    if (!mConfigInit) {
+        for (int32_t prop : props) {
+            auto maybeConfig = mVehicleHardware->getPropertyConfig(prop);
+            if (!maybeConfig.has_value() ||
+                !isConfigSupportedForCurrentVhalVersion(maybeConfig.value())) {
+                return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                        toInt(StatusCode::INVALID_ARG),
+                        StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
+            }
+            configs.push_back(maybeConfig.value());
         }
+
+        return vectorToStableLargeParcelable(std::move(configs), output);
     }
+
+    ScopedAStatus status = ScopedAStatus::ok();
+    getConfigsByPropId([this, &configs, &status, &props](const auto& configsByPropId) {
+        SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+        for (int32_t prop : props) {
+            auto it = configsByPropId.find(prop);
+            if (it != configsByPropId.end()) {
+                configs.push_back(it->second);
+            } else {
+                status = ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                        toInt(StatusCode::INVALID_ARG),
+                        StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
+                return;
+            }
+        }
+    });
+
+    if (!status.isOk()) {
+        return status;
+    }
+
     return vectorToStableLargeParcelable(std::move(configs), output);
 }
 
@@ -691,8 +761,8 @@
 }
 
 VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
-        const std::vector<SubscribeOptions>& options) {
-    const auto& configsByPropId = getConfigsByPropId();
+        const std::vector<SubscribeOptions>& options,
+        const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId) {
     for (const auto& option : options) {
         int32_t propId = option.propId;
         auto it = configsByPropId.find(propId);
@@ -757,23 +827,15 @@
             }
         }
     }
+
     return {};
 }
 
-ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
-                                           const std::vector<SubscribeOptions>& options,
-                                           [[maybe_unused]] int32_t maxSharedMemoryFileCount) {
-    // TODO(b/205189110): Use shared memory file count.
-    if (callback == nullptr) {
-        return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
-    }
-    if (auto result = checkSubscribeOptions(options); !result.ok()) {
-        ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
-        return toScopedAStatus(result);
-    }
-    std::vector<SubscribeOptions> onChangeSubscriptions;
-    std::vector<SubscribeOptions> continuousSubscriptions;
-    const auto& configsByPropId = getConfigsByPropId();
+void DefaultVehicleHal::parseSubscribeOptions(
+        const std::vector<SubscribeOptions>& options,
+        const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId,
+        std::vector<SubscribeOptions>& onChangeSubscriptions,
+        std::vector<SubscribeOptions>& continuousSubscriptions) {
     for (const auto& option : options) {
         int32_t propId = option.propId;
         // We have already validate config exists.
@@ -831,6 +893,34 @@
             onChangeSubscriptions.push_back(std::move(optionCopy));
         }
     }
+}
+
+ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
+                                           const std::vector<SubscribeOptions>& options,
+                                           [[maybe_unused]] int32_t maxSharedMemoryFileCount) {
+    // TODO(b/205189110): Use shared memory file count.
+    if (callback == nullptr) {
+        return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+    }
+    std::vector<SubscribeOptions> onChangeSubscriptions;
+    std::vector<SubscribeOptions> continuousSubscriptions;
+    ScopedAStatus returnStatus = ScopedAStatus::ok();
+    getConfigsByPropId([this, &returnStatus, &options, &onChangeSubscriptions,
+                        &continuousSubscriptions](const auto& configsByPropId) {
+        SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+        if (auto result = checkSubscribeOptions(options, configsByPropId); !result.ok()) {
+            ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
+            returnStatus = toScopedAStatus(result);
+            return;
+        }
+        parseSubscribeOptions(options, configsByPropId, onChangeSubscriptions,
+                              continuousSubscriptions);
+    });
+
+    if (!returnStatus.isOk()) {
+        return returnStatus;
+    }
 
     {
         // Lock to make sure onBinderDied would not be called concurrently.
@@ -891,13 +981,13 @@
         return StatusError(StatusCode::INVALID_ARG) << getErrorMsg(result);
     }
 
-    const VehiclePropConfig* config = result.value();
-    const VehicleAreaConfig* areaConfig = getAreaConfig(value, *config);
+    const VehiclePropConfig& config = result.value();
+    const VehicleAreaConfig* areaConfig = getAreaConfig(value, config);
 
     if (areaConfig == nullptr && !isGlobalProp(propId)) {
         return StatusError(StatusCode::INVALID_ARG) << "no config for area ID: " << value.areaId;
     }
-    if (!hasRequiredAccess(config->access, accessToTest) &&
+    if (!hasRequiredAccess(config.access, accessToTest) &&
         (areaConfig == nullptr || !hasRequiredAccess(areaConfig->access, accessToTest))) {
         return StatusError(StatusCode::ACCESS_DENIED)
                << StringPrintf("Property %" PRId32 " does not have the following access: %" PRId32,
@@ -966,7 +1056,6 @@
     }
     DumpResult result = mVehicleHardware->dump(options);
     if (result.refreshPropertyConfigs) {
-        std::scoped_lock lockGuard(mConfigInitLock);
         getAllPropConfigsFromHardwareLocked();
     }
     dprintf(fd, "%s", (result.buffer + "\n").c_str());
@@ -974,11 +1063,16 @@
         return STATUS_OK;
     }
     dprintf(fd, "Vehicle HAL State: \n");
-    const auto& configsByPropId = getConfigsByPropId();
+    std::unordered_map<int32_t, VehiclePropConfig> configsByPropIdCopy;
+    getConfigsByPropId([this, &configsByPropIdCopy](const auto& configsByPropId) {
+        SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+        configsByPropIdCopy = configsByPropId;
+    });
     {
         std::scoped_lock<std::mutex> lockGuard(mLock);
         dprintf(fd, "Interface version: %" PRId32 "\n", getVhalInterfaceVersion());
-        dprintf(fd, "Containing %zu property configs\n", configsByPropId.size());
+        dprintf(fd, "Containing %zu property configs\n", configsByPropIdCopy.size());
         dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
         dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
         dprintf(fd, "Currently have %zu subscribe clients\n", countSubscribeClients());
diff --git a/automotive/vehicle/aidl/impl/vhal/src/fuzzer.cpp b/automotive/vehicle/aidl/impl/vhal/src/fuzzer.cpp
index ac1e3b1..6d994bb 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/fuzzer.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/fuzzer.cpp
@@ -25,6 +25,8 @@
 using ::ndk::SharedRefBase;
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    // TODO(b/183141167): need to rewrite 'dump' to avoid SIGPIPE.
+    signal(SIGPIPE, SIG_IGN);
     std::unique_ptr<FakeVehicleHardware> hardware = std::make_unique<FakeVehicleHardware>();
     std::shared_ptr<DefaultVehicleHal> vhal =
             ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index 11a8fc7..4891bf5 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -650,6 +650,8 @@
 
     auto hardware = std::make_unique<MockVehicleHardware>();
     hardware->setPropertyConfigs(testConfigs);
+    // Store the pointer for testing. We are sure it is valid.
+    MockVehicleHardware* hardwarePtr = hardware.get();
     auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
     std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
 
@@ -658,6 +660,7 @@
 
     ASSERT_TRUE(status.isOk()) << "getPropConfigs failed: " << status.getMessage();
     ASSERT_EQ(output.payloads, testConfigs);
+    ASSERT_FALSE(hardwarePtr->getAllPropertyConfigsCalled());
 }
 
 TEST_F(DefaultVehicleHalTest, testGetPropConfigsInvalidArg) {
@@ -704,6 +707,34 @@
     ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
     EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch";
     EXPECT_EQ(countClients(), static_cast<size_t>(1));
+    ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesSmall_AfterGetAllPropConfigs) {
+    GetValueRequests requests;
+    std::vector<GetValueResult> expectedResults;
+    std::vector<GetValueRequest> expectedHardwareRequests;
+
+    // If we already called getAllPropConfigs, the configs will be cached.
+    VehiclePropConfigs output;
+    getClient()->getAllPropConfigs(&output);
+
+    ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+    getHardware()->addGetValueResponses(expectedResults);
+
+    auto status = getClient()->getValues(getCallbackClient(), requests);
+
+    ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
+
+    EXPECT_EQ(getHardware()->nextGetValueRequests(), expectedHardwareRequests)
+            << "requests to hardware mismatch";
+
+    auto maybeGetValueResults = getCallback()->nextGetValueResults();
+    ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
+    EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch";
+    EXPECT_EQ(countClients(), static_cast<size_t>(1));
+    ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled());
 }
 
 TEST_F(DefaultVehicleHalTest, testGetValuesLarge) {
@@ -1016,6 +1047,34 @@
     ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
     ASSERT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch";
     EXPECT_EQ(countClients(), static_cast<size_t>(1));
+    ASSERT_FALSE(getHardware()->getAllPropertyConfigsCalled());
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesSmall_AfterGetAllPropConfigs) {
+    SetValueRequests requests;
+    std::vector<SetValueResult> expectedResults;
+    std::vector<SetValueRequest> expectedHardwareRequests;
+
+    // If we already called getAllPropConfigs, the configs will be cached.
+    VehiclePropConfigs output;
+    getClient()->getAllPropConfigs(&output);
+
+    ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+    getHardware()->addSetValueResponses(expectedResults);
+
+    auto status = getClient()->setValues(getCallbackClient(), requests);
+
+    ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
+
+    EXPECT_EQ(getHardware()->nextSetValueRequests(), expectedHardwareRequests)
+            << "requests to hardware mismatch";
+
+    auto maybeSetValueResults = getCallback()->nextSetValueResults();
+    ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
+    ASSERT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch";
+    EXPECT_EQ(countClients(), static_cast<size_t>(1));
+    ASSERT_TRUE(getHardware()->getAllPropertyConfigsCalled());
 }
 
 TEST_F(DefaultVehicleHalTest, testSetValuesLarge) {
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
index db15c89..e796ce5 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
@@ -45,9 +45,20 @@
 
 std::vector<VehiclePropConfig> MockVehicleHardware::getAllPropertyConfigs() const {
     std::scoped_lock<std::mutex> lockGuard(mLock);
+    mGetAllPropertyConfigsCalled = true;
     return mPropertyConfigs;
 }
 
+std::optional<VehiclePropConfig> MockVehicleHardware::getPropertyConfig(int32_t propId) const {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    for (const auto& config : mPropertyConfigs) {
+        if (config.prop == propId) {
+            return config;
+        }
+    }
+    return std::nullopt;
+}
+
 StatusCode MockVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback,
                                           const std::vector<SetValueRequest>& requests) {
     std::scoped_lock<std::mutex> lockGuard(mLock);
@@ -336,6 +347,11 @@
     (*mPropertySetErrorCallback)(errorEvents);
 }
 
+bool MockVehicleHardware::getAllPropertyConfigsCalled() {
+    std::scoped_lock<std::mutex> lockGuard(mLock);
+    return mGetAllPropertyConfigsCalled;
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
index eeca582..06e01a8 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
@@ -47,6 +47,8 @@
 
     std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
     getAllPropertyConfigs() const override;
+    std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+    getPropertyConfig(int32_t propId) const override;
     aidl::android::hardware::automotive::vehicle::StatusCode setValues(
             std::shared_ptr<const SetValuesCallback> callback,
             const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
@@ -98,6 +100,9 @@
     std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>
     getSubscribeOptions();
     void clearSubscribeOptions();
+    // Whether getAllPropertyConfigs() has been called, which blocks all all property configs
+    // being ready.
+    bool getAllPropertyConfigsCalled();
 
   private:
     mutable std::mutex mLock;
@@ -143,6 +148,8 @@
 
     DumpResult mDumpResult;
 
+    mutable bool mGetAllPropertyConfigsCalled GUARDED_BY(mLock) = false;
+
     // RecurrentTimer is thread-safe.
     std::shared_ptr<RecurrentTimer> mRecurrentTimer;
     std::unordered_map<int32_t, std::unordered_map<int32_t, std::shared_ptr<std::function<void()>>>>
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
index 0863adf..e5c09b0 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -1677,6 +1677,12 @@
      * For configuration information, VehiclePropConfig.configArray must have bit flag combining
      * values in VehicleApPowerStateConfigFlag.
      *
+     *   configArray[0] : Bit flag combining values in VehicleApPowerStateConfigFlag,
+     *                    0x0 if not used,
+     *                    0x1 for enabling suspend to ram,
+     *                    0x2 for supporting powering on AP from off state after timeout.
+     *                    0x4 for enabling suspend to disk,
+     *
      *   int32Values[0] : VehicleApPowerStateReq enum value
      *   int32Values[1] : additional parameter relevant for each state,
      *                    0 if not used.
diff --git a/automotive/vehicle/tools/generate_emu_metadata/src/com/android/car/tool/EmuMetadataGenerator.java b/automotive/vehicle/tools/generate_emu_metadata/src/com/android/car/tool/EmuMetadataGenerator.java
index bea5951..7f4ceb8 100644
--- a/automotive/vehicle/tools/generate_emu_metadata/src/com/android/car/tool/EmuMetadataGenerator.java
+++ b/automotive/vehicle/tools/generate_emu_metadata/src/com/android/car/tool/EmuMetadataGenerator.java
@@ -79,17 +79,18 @@
             + "either this or input_files must be specified\n" + INPUT_FILES_OPTION
             + ": one or more Java files, this is used to decide the input "
             + "directory\n" + PACKAGE_NAME_OPTION
-            + ": the optional package name for the interface, by default is " + DEFAULT_PACKAGE_NAME
-            + "\n" + OUTPUT_JSON_OPTION + ": The output JSON file\n" + OUTPUT_EMPTY_FILE_OPTION
-            + ": Only used for check_mode, this file will be created if "
+            + ": the optional package name for the interface, by default is "
+            + DEFAULT_PACKAGE_NAME + "\n" + OUTPUT_JSON_OPTION + ": The output JSON file\n"
+            + OUTPUT_EMPTY_FILE_OPTION + ": Only used for check_mode, this file will be created if "
             + "check  passed\n" + CHECK_AGAINST_OPTION
             + ": An optional JSON file to check against. If specified, the "
-            + "generated output file will be checked against this file, if they are not the same, "
+            + ("generated output file will be checked against this file, if they are not the "
+                    + "same, ")
             + "the script will fail, otherwise, the output_empty_file will be created\n"
             + "For example: \n"
             + "EnumMetadataGenerator --input_dir out/soong/.intermediates/hardware/"
             + "interfaces/automotive/vehicle/aidl_property/android.hardware.automotive.vehicle."
-            + "property-V3-java-source/gen/ --package_name android.hardware.automotive.vehicle "
+            + "property-V4-java-source/gen/ --package_name android.hardware.automotive.vehicle "
             + "--output_json /tmp/android.hardware.automotive.vehicle-types-meta.json";
     private static final String VEHICLE_PROPERTY_FILE = "VehicleProperty.java";
     private static final String CHECK_FILE_PATH =
diff --git a/automotive/vehicle/vhal_static_cpp_lib.mk b/automotive/vehicle/vhal_static_cpp_lib.mk
index 6b3d486..9371453 100644
--- a/automotive/vehicle/vhal_static_cpp_lib.mk
+++ b/automotive/vehicle/vhal_static_cpp_lib.mk
@@ -17,4 +17,4 @@
 
 LOCAL_STATIC_LIBRARIES += \
     android.hardware.automotive.vehicle-V3-ndk \
-    android.hardware.automotive.vehicle.property-V3-ndk
+    android.hardware.automotive.vehicle.property-V4-ndk
diff --git a/automotive/vehicle/vts/Android.bp b/automotive/vehicle/vts/Android.bp
index 40aec59..d55dc33 100644
--- a/automotive/vehicle/vts/Android.bp
+++ b/automotive/vehicle/vts/Android.bp
@@ -15,6 +15,7 @@
  */
 
 package {
+    default_team: "trendy_team_aaos_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
@@ -43,7 +44,7 @@
         "vhalclient_defaults",
     ],
     header_libs: [
-        "IVehicleGeneratedHeaders-V3",
+        "IVehicleGeneratedHeaders-V4",
     ],
     test_suites: [
         "general-tests",
diff --git a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
index 608a328..fb3c8cd 100644
--- a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
+++ b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
@@ -95,7 +95,7 @@
             std::lock_guard<std::mutex> lockGuard(mLock);
             for (auto& value : values) {
                 int32_t propId = value->getPropId();
-                mEvents[propId].push_back(std::move(value->clone()));
+                mEvents[propId].push_back(value->clone());
             }
         }
         mEventCond.notify_one();
@@ -122,7 +122,7 @@
             return events;
         }
         for (const auto& eventPtr : mEvents[propId]) {
-            events.push_back(std::move(eventPtr->clone()));
+            events.push_back(eventPtr->clone());
         }
         return events;
     }
diff --git a/biometrics/common/aidl/Android.bp b/biometrics/common/aidl/Android.bp
index 246bcf2..8c9a357 100644
--- a/biometrics/common/aidl/Android.bp
+++ b/biometrics/common/aidl/Android.bp
@@ -22,6 +22,15 @@
         cpp: {
             enabled: false,
         },
+        ndk: {
+            apex_available: [
+                "//apex_available:anyapex",
+                "//apex_available:platform",
+            ],
+        },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
diff --git a/biometrics/common/config/Android.bp b/biometrics/common/config/Android.bp
index d38ffe8..b86aafa 100644
--- a/biometrics/common/config/Android.bp
+++ b/biometrics/common/config/Android.bp
@@ -22,7 +22,7 @@
     //   SPDX-license-identifier-Apache-2.0
     name: "android.hardware.biometrics.common.config",
     export_include_dirs: ["include"],
-    vendor: true,
+    vendor_available: true,
     srcs: [
         "Config.cpp",
     ],
@@ -30,6 +30,10 @@
         "libbase",
         "libbinder_ndk",
     ],
+    apex_available: [
+        "//apex_available:anyapex",
+        "//apex_available:platform",
+    ],
 }
 
 cc_test_host {
diff --git a/biometrics/common/config/include/config/Config.h b/biometrics/common/config/include/config/Config.h
index 0367832..b1affdc 100644
--- a/biometrics/common/config/include/config/Config.h
+++ b/biometrics/common/config/include/config/Config.h
@@ -100,7 +100,11 @@
         } else if (std::holds_alternative<OptIntVec>(v)) {
             for (auto x : std::get<OptIntVec>(v))
                 if (x.has_value()) os << x.value() << " ";
+        } else if (std::holds_alternative<OptString>(v)) {
+            OptString ov = std::get<OptString>(v);
+            if (ov.has_value()) os << ov.value();
         }
+
         return os.str();
     }
     std::string toString() const {
diff --git a/biometrics/common/thread/Android.bp b/biometrics/common/thread/Android.bp
index e7a7e4c..c1ebe3b 100644
--- a/biometrics/common/thread/Android.bp
+++ b/biometrics/common/thread/Android.bp
@@ -10,10 +10,14 @@
     //   SPDX-license-identifier-Apache-2.0
     name: "android.hardware.biometrics.common.thread",
     export_include_dirs: ["include"],
-    vendor: true,
+    vendor_available: true,
     srcs: [
         "WorkerThread.cpp",
     ],
+    apex_available: [
+        "//apex_available:anyapex",
+        "//apex_available:platform",
+    ],
 }
 
 cc_test_host {
diff --git a/biometrics/common/util/Android.bp b/biometrics/common/util/Android.bp
index 599c491..a0bd211 100644
--- a/biometrics/common/util/Android.bp
+++ b/biometrics/common/util/Android.bp
@@ -6,7 +6,7 @@
     //   SPDX-license-identifier-Apache-2.0
     name: "android.hardware.biometrics.common.util",
     export_include_dirs: ["include"],
-    vendor: true,
+    vendor_available: true,
     srcs: [
         "CancellationSignal.cpp",
     ],
@@ -15,4 +15,8 @@
         "libbinder_ndk",
         "android.hardware.biometrics.common-V4-ndk",
     ],
+    apex_available: [
+        "//apex_available:anyapex",
+        "//apex_available:platform",
+    ],
 }
diff --git a/biometrics/face/1.0/vts/functional/Android.bp b/biometrics/face/1.0/vts/functional/Android.bp
index 259c4ec..4c06121 100644
--- a/biometrics/face/1.0/vts/functional/Android.bp
+++ b/biometrics/face/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_biometrics_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/biometrics/face/aidl/Android.bp b/biometrics/face/aidl/Android.bp
index fadcde7..54d01a7 100644
--- a/biometrics/face/aidl/Android.bp
+++ b/biometrics/face/aidl/Android.bp
@@ -11,7 +11,7 @@
     name: "android.hardware.biometrics.face",
     vendor_available: true,
     srcs: [
-        "android/hardware/biometrics/face/**/*.aidl",
+        "android/hardware/biometrics/face/*.aidl",
     ],
     imports: [
         "android.hardware.biometrics.common-V4",
@@ -36,6 +36,10 @@
             additional_shared_libraries: [
                 "libnativewindow",
             ],
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.hardware.biometrics.face.virtual",
+            ],
         },
     },
     versions_with_info: [
@@ -74,5 +78,39 @@
 
     ],
     frozen: true,
+}
 
+aidl_interface {
+    name: "android.hardware.biometrics.face.virtualhal",
+    srcs: [
+        "android/hardware/biometrics/face/virtualhal/*.aidl",
+    ],
+    imports: [
+        "android.hardware.biometrics.common-V4",
+        "android.hardware.keymaster-V4",
+        "android.hardware.biometrics.face-V4",
+    ],
+    vendor_available: true,
+    unstable: true,
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        rust: {
+            enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+        ndk: {
+            additional_shared_libraries: [
+                "libnativewindow",
+            ],
+            apex_available: [
+                "com.android.hardware.biometrics.face.virtual",
+                "//apex_available:platform",
+            ],
+        },
+    },
+    frozen: false,
 }
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
index 26cb361..0dbf052 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
@@ -73,7 +73,7 @@
      * Note that this interface allows multiple in-flight challenges. Invoking generateChallenge
      * twice does not invalidate the first challenge. The challenge is invalidated only when:
      *   1) Its lifespan exceeds the challenge timeout defined in the TEE.
-     *   2) IFingerprint#revokeChallenge is invoked
+     *   2) IFace#revokeChallenge is invoked
      *
      * For example, the following is a possible table of valid challenges:
      * ----------------------------------------------
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/AcquiredInfoAndVendorCode.aidl
similarity index 86%
copy from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/AcquiredInfoAndVendorCode.aidl
index c7be950..a254120 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/AcquiredInfoAndVendorCode.aidl
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.biometrics.face.virtualhal;
 
-import android.hardware.biometrics.fingerprint.AcquiredInfo;
+import android.hardware.biometrics.face.AcquiredInfo;
 
 /**
  * @hide
  */
-@VintfStability
 union AcquiredInfoAndVendorCode {
     /**
      * Acquired info as specified in AcqauiredInfo.aidl
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/EnrollmentProgressStep.aidl
similarity index 82%
copy from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
copy to biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/EnrollmentProgressStep.aidl
index bf038f6..7fbcf5d 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/EnrollmentProgressStep.aidl
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.biometrics.face.virtualhal;
 
-import android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode;
+import android.hardware.biometrics.face.virtualhal.AcquiredInfoAndVendorCode;
 
 /**
  * @hide
  */
-@VintfStability
 parcelable EnrollmentProgressStep {
     /**
      * The duration of the enrollment step in milli-seconds
@@ -30,7 +29,7 @@
 
     /**
      * The sequence of acquired info and vendor code to be issued by HAL during the step.
-     * The codes are evenly spreaded over the duration
+     * The codes are evenly spread over the duration
      */
     AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes;
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/IVirtualHal.aidl
similarity index 71%
copy from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
copy to biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/IVirtualHal.aidl
index cb9135e..1d3d934 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/IVirtualHal.aidl
@@ -14,19 +14,18 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.biometrics.face.virtualhal;
 
 import android.hardware.biometrics.common.SensorStrength;
-import android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode;
-import android.hardware.biometrics.fingerprint.FingerprintSensorType;
-import android.hardware.biometrics.fingerprint.NextEnrollment;
-import android.hardware.biometrics.fingerprint.SensorLocation;
+import android.hardware.biometrics.face.FaceSensorType;
+import android.hardware.biometrics.face.IFace;
+import android.hardware.biometrics.face.virtualhal.AcquiredInfoAndVendorCode;
+import android.hardware.biometrics.face.virtualhal.NextEnrollment;
 
 /**
  * @hide
  */
-@VintfStability
-oneway interface IVirtualHal {
+interface IVirtualHal {
     /**
      * The operation failed due to invalid input parameters, the error messages should
      * gives more details
@@ -34,13 +33,13 @@
     const int STATUS_INVALID_PARAMETER = 1;
 
     /**
-     * Set Fingerprint Virtual HAL behavior parameters
+     * Set Face Virtual HAL behavior parameters
      */
 
     /**
      * setEnrollments
      *
-     * Set the ids of the fingerprints that were currently enrolled in the Virtual HAL,
+     * Set the ids of the faces that were currently enrolled in the Virtual HAL,
      *
      * @param ids ids can contain 1 or more ids, each must be larger than 0
      */
@@ -49,7 +48,7 @@
     /**
      * setEnrollmentHit
      *
-     * Set current fingerprint enrollment ids in Fingerprint Virtual HAL,
+     * Set current face enrollment ids in Face Virtual HAL,
      *
      * @param ids ids can contain 1 or more ids, each must be larger than 0
      */
@@ -67,7 +66,7 @@
     /**
      * setAuthenticatorId
      *
-     * Set authenticator id in virtual HAL, the id is returned in ISession#getAuthenticatorId() call
+     * Set authenticator id in virtual HAL, the id is returned in ISession#AuthenticatorId() call
      *
      * @param id authenticator id value, only applied to the sensor with SensorStrength::STRONG.
      */
@@ -116,7 +115,7 @@
      * setOperationAuthenticateDuration
      *
      * Set authentication duration covering the HAL authetication from start to end, including
-     * fingerprint capturing, and matching, acquired info reporting. In case a sequence of acquired
+     * face capturing, and matching, acquired info reporting. In case a sequence of acquired
      * info code are specified via setOperationAuthenticateAcquired(), the reporting is evenly
      * distributed over the duration.
      *
@@ -130,7 +129,9 @@
      * setOperationAuthenticateError
      *
      * Force authentication to error out for non-zero error
-     * Check hardware/interfaces/biometrics/fingerprint/aidl/default/README.md for valid error codes
+     * Check
+     * hardware/interfaces/biometrics/face/aidl/default/aidl/android/hardware/biometrics/face/Error.aidl
+     * for valid error codes
      *
      * @param error if error < 1000
      *                  non-vendor error
@@ -143,27 +144,15 @@
      * setOperationAuthenticateAcquired
      *
      * Set one of more acquired info codes for the virtual hal to report during authentication
-     * Check hardware/interfaces/biometrics/fingerprint/aidl/default/README.md for valid acquired
-     * info codes
+     * Check
+     * hardware/interfaces/biometrics/face/aidl/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
+     * for valid acquired info codes
      *
      * @param acquired[], one or more acquired info codes
      */
     void setOperationAuthenticateAcquired(in AcquiredInfoAndVendorCode[] acquired);
 
     /**
-     * setOperationEnrollError
-     *
-     * Force enrollment operation to error out for non-zero error
-     * Check hardware/interfaces/biometrics/fingerprint/aidl/default/README.md for valid error codes
-     *
-     * @param error if error < 1000
-     *                  non-vendor error
-     *              else
-     *                  vendor error
-     */
-    void setOperationEnrollError(in int error);
-
-    /**
      * setOperationEnrollLatency
      *
      * Set enrollment latency in the virtual hal in a fixed value (single element) or random
@@ -202,42 +191,11 @@
     void setOperationDetectInteractionLatency(in int[] latencyMs);
 
     /**
-     * setOperationDetectInteractionError
+     * setOperationDetectInteractionFails
      *
-     * Force detect interaction operation to error out for non-zero error
-     * Check hardware/interfaces/biometrics/fingerprint/aidl/default/README.md for valid error codes
-     *
-     * @param error if error < 1000
-     *                  non-vendor error
-     *              else
-     *                  vendor error
+     * Force detect interaction operation to fail
      */
-    void setOperationDetectInteractionError(in int error);
-
-    /**
-     * setOperationDetectInteractionDuration
-     *
-     * Set detect interaction duration covering the HAL authetication from start to end, including
-     * fingerprint detect and acquired info reporting. In case a sequence of acquired info code are
-     * specified via setOperationDetectInteractionAcquired(), the reporting is evenly distributed
-     * over the duration.
-     *
-     * This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
-     *
-     * @param duration  value is in milli-seconds
-     */
-    void setOperationDetectInteractionDuration(in int durationMs);
-
-    /**
-     * setOperationDetectInteractionAcquired
-     *
-     * Set one of more acquired info codes for the virtual hal to report during detect interaction
-     * Check hardware/interfaces/biometrics/fingerprint/aidl/default/README.md for valid acquired
-     * info codes
-     *
-     * @param acquired[], one or more acquired info codes
-     */
-    void setOperationDetectInteractionAcquired(in AcquiredInfoAndVendorCode[] acquired);
+    void setOperationDetectInteractionFails(in boolean error);
 
     /**
      * setLockout
@@ -261,6 +219,15 @@
     void setLockoutEnable(in boolean enable);
 
     /**
+     * setLockoutTimedEnable
+     *
+     * Whether to enable authentication-fail-based time-based-lockout tracking or not.
+     *
+     * @param enable, set true to enable the time-basedlockout tracking
+     */
+    void setLockoutTimedEnable(in boolean enable);
+
+    /**
      * setLockoutTimedThreshold
      *
      * Set the number of consecutive authentication failures that triggers the timed-based lock to
@@ -303,16 +270,28 @@
     void resetConfigurations();
 
     /**
-     * The following functions are used to configure Fingerprint Virtual HAL sensor properties
-     *  refer to SensorProps.aidl and CommonProps.aidl for details of each property
+     * setType
+     *
+     * Configure virtual face sensor type
+     *
+     * @param type, sensor type as specified in FaceSensorType.aidl
+     *
      */
-    void setType(in FingerprintSensorType type);
-    void setSensorId(in int id);
+    void setType(in FaceSensorType type);
+
+    /**
+     *  setSensorStrength
+     *
+     *  Configure virtual face sensor strength
+     *
+     * @param sensor strength as specified in common/SensorStrength.aidl
+     */
     void setSensorStrength(in SensorStrength strength);
-    void setMaxEnrollmentPerUser(in int max);
-    void setSensorLocation(in SensorLocation loc);
-    void setNavigationGuesture(in boolean v);
-    void setDetectInteraction(in boolean v);
-    void setDisplayTouch(in boolean v);
-    void setControlIllumination(in boolean v);
+
+    /**
+     * getFaceHal
+     *
+     * @return IFace interface associated with IVirtualHal instance
+     */
+    IFace getFaceHal();
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/NextEnrollment.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/NextEnrollment.aidl
similarity index 87%
rename from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
rename to biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/NextEnrollment.aidl
index 4b50850..d3547a8 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/NextEnrollment.aidl
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.biometrics.face.virtualhal;
 
 /**
  * @hide
  */
-@VintfStability
 parcelable NextEnrollment {
     /**
      *  Identifier of the next enrollment if successful
@@ -31,7 +30,7 @@
      *  and sequence of acquired info codes to be generated by HAL.
      *  See EnrollmentProgressStep.aidl for more details
      */
-    android.hardware.biometrics.fingerprint.EnrollmentProgressStep[] progressSteps;
+    android.hardware.biometrics.face.virtualhal.EnrollmentProgressStep[] progressSteps;
 
     /**
      * Success or failure of the next enrollment
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/README.md b/biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/README.md
new file mode 100644
index 0000000..bf1a4b1
--- /dev/null
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/virtualhal/README.md
@@ -0,0 +1,3 @@
+The aidl files in this directory are used to control/configure face virtual hal
+via IVirtualHal interface
+
diff --git a/biometrics/face/aidl/default/Android.bp b/biometrics/face/aidl/default/Android.bp
index 685639c..dc11af6 100644
--- a/biometrics/face/aidl/default/Android.bp
+++ b/biometrics/face/aidl/default/Android.bp
@@ -9,21 +9,13 @@
 }
 
 filegroup {
-    name: "face-example.rc",
-    srcs: ["face-example.rc"],
+    name: "face-virtual.rc",
+    srcs: ["face-virtual.rc"],
 }
 
-filegroup {
-    name: "face-example.xml",
-    srcs: ["face-example.xml"],
-}
-
-cc_binary {
-    name: "android.hardware.biometrics.face-service.example",
-    relative_install_path: "hw",
-    init_rc: [":face-example.rc"],
-    vintf_fragments: [":face-example.xml"],
-    vendor: true,
+cc_library_static {
+    name: "android.hardware.biometrics.face-service.lib",
+    vendor_available: true,
 
     shared_libs: [
         "libbinder_ndk",
@@ -32,32 +24,86 @@
     ],
     srcs: [
         "FakeLockoutTracker.cpp",
-        "main.cpp",
         "Face.cpp",
         "FakeFaceEngine.cpp",
         "Session.cpp",
+        "FaceConfig.cpp",
+        "VirtualHal.cpp",
+        "main.cpp",
     ],
     include_dirs: [
         "frameworks/native/aidl/gui",
     ],
     stl: "c++_static",
-    static_libs: [
+    whole_static_libs: [
         "android.hardware.biometrics.common-V4-ndk",
+        "android.hardware.biometrics.common.config",
         "android.hardware.biometrics.common.thread",
         "android.hardware.biometrics.common.util",
+        "android.hardware.biometrics.face.virtualhal-ndk",
         "android.hardware.biometrics.face-V4-ndk",
         "android.hardware.common-V2-ndk",
         "android.hardware.keymaster-V4-ndk",
         "libandroid.hardware.biometrics.face.VirtualProps",
         "libbase",
     ],
+    apex_available: [
+        "com.android.hardware.biometrics.face.virtual",
+        "//apex_available:platform",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.biometrics.face-service.example",
+    system_ext_specific: true,
+    relative_install_path: "hw",
+
+    shared_libs: [
+        "libbinder_ndk",
+        "liblog",
+        "libnativewindow",
+    ],
+    whole_static_libs: [
+        "android.hardware.biometrics.face-service.lib",
+    ],
+    installable: false, // install APEX instead
+    apex_available: [
+        "com.android.hardware.biometrics.face.virtual",
+        "//apex_available:platform",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.biometrics.face-service.default",
+    vendor: true,
+    relative_install_path: "hw",
+    init_rc: ["face-default.rc"],
+    vintf_fragment_modules: ["android.hardware.biometrics.face-service.default.vintf"],
+    shared_libs: [
+        "libbinder_ndk",
+        "liblog",
+        "libnativewindow",
+    ],
+    whole_static_libs: [
+        "android.hardware.biometrics.face-service.lib",
+    ],
+}
+
+vintf_fragment {
+    name: "android.hardware.biometrics.face-service.default.vintf",
+    src: "face-default.xml",
+    vendor: true,
 }
 
 sysprop_library {
     name: "android.hardware.biometrics.face.VirtualProps",
     srcs: ["face.sysprop"],
-    property_owner: "Vendor",
-    vendor: true,
+    property_owner: "Platform",
+    vendor_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.hardware.biometrics.face.virtual",
+    ],
 }
 
 cc_test {
@@ -66,6 +112,7 @@
         "tests/FakeFaceEngineTest.cpp",
         "FakeFaceEngine.cpp",
         "FakeLockoutTracker.cpp",
+        "FaceConfig.cpp",
     ],
     shared_libs: [
         "libbase",
@@ -81,6 +128,8 @@
         "android.hardware.biometrics.common-V4-ndk",
         "android.hardware.keymaster-V4-ndk",
         "android.hardware.biometrics.common.util",
+        "android.hardware.biometrics.common.config",
+        "android.hardware.biometrics.common.thread",
     ],
     vendor: true,
     test_suites: ["general-tests"],
@@ -92,6 +141,7 @@
     srcs: [
         "tests/FakeLockoutTrackerTest.cpp",
         "FakeLockoutTracker.cpp",
+        "FaceConfig.cpp",
     ],
     shared_libs: [
         "libbase",
@@ -107,8 +157,45 @@
         "android.hardware.biometrics.common-V4-ndk",
         "android.hardware.keymaster-V4-ndk",
         "android.hardware.biometrics.common.util",
+        "android.hardware.biometrics.common.config",
+        "android.hardware.biometrics.common.thread",
     ],
     vendor: true,
     test_suites: ["general-tests"],
     require_root: true,
 }
+
+cc_test {
+    name: "android.hardware.biometrics.face.VirtualHalTest",
+    srcs: [
+        "tests/VirtualHalTest.cpp",
+        "FakeLockoutTracker.cpp",
+        "Face.cpp",
+        "FakeFaceEngine.cpp",
+        "Session.cpp",
+        "VirtualHal.cpp",
+        "FaceConfig.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libnativewindow",
+        "liblog",
+    ],
+    include_dirs: [
+        "frameworks/native/aidl/gui",
+    ],
+    static_libs: [
+        "android.hardware.biometrics.common-V4-ndk",
+        "android.hardware.biometrics.common.config",
+        "android.hardware.biometrics.common.thread",
+        "android.hardware.biometrics.common.util",
+        "android.hardware.biometrics.face-V4-ndk",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.keymaster-V4-ndk",
+        "libandroid.hardware.biometrics.face.VirtualProps",
+        "android.hardware.biometrics.face.virtualhal-ndk",
+    ],
+    test_suites: ["general-tests"],
+    require_root: true,
+}
diff --git a/biometrics/face/aidl/default/Face.cpp b/biometrics/face/aidl/default/Face.cpp
index 5ae0df6..1543007 100644
--- a/biometrics/face/aidl/default/Face.cpp
+++ b/biometrics/face/aidl/default/Face.cpp
@@ -34,9 +34,7 @@
 namespace aidl::android::hardware::biometrics::face {
 
 const int kSensorId = 4;
-const common::SensorStrength kSensorStrength = FakeFaceEngine::GetSensorStrength();
 const int kMaxEnrollmentsPerUser = 5;
-const FaceSensorType kSensorType = FakeFaceEngine::GetSensorType();
 const bool kHalControlsPreview = true;
 const std::string kHwComponentId = "faceSensor";
 const std::string kHardwareVersion = "vendor/model/revision";
@@ -62,13 +60,13 @@
 
     common::CommonProps commonProps;
     commonProps.sensorId = kSensorId;
-    commonProps.sensorStrength = kSensorStrength;
+    commonProps.sensorStrength = FakeFaceEngine::GetSensorStrength();
     commonProps.maxEnrollmentsPerUser = kMaxEnrollmentsPerUser;
     commonProps.componentInfo = {std::move(hw_component_info), std::move(sw_component_info)};
 
     SensorProps props;
     props.commonProps = std::move(commonProps);
-    props.sensorType = kSensorType;
+    props.sensorType = FakeFaceEngine::GetSensorType();
     props.halControlsPreview = kHalControlsPreview;
     props.enrollPreviewWidth = 1080;
     props.enrollPreviewHeight = 1920;
@@ -141,6 +139,30 @@
     return STATUS_OK;
 }
 
+const char* Face::type2String(FaceSensorType type) {
+    switch (type) {
+        case FaceSensorType::RGB:
+            return "rgb";
+        case FaceSensorType::IR:
+            return "ir";
+        default:
+            return "unknown";
+    }
+}
+
+const char* Face::strength2String(common::SensorStrength strength) {
+    switch (strength) {
+        case common::SensorStrength::STRONG:
+            return "STRONG";
+        case common::SensorStrength::WEAK:
+            return "WEAK";
+        case common::SensorStrength::CONVENIENCE:
+            return "CONVENIENCE";
+        default:
+            return "unknown";
+    }
+}
+
 void Face::onHelp(int fd) {
     dprintf(fd, "Virtual Face HAL commands:\n");
     dprintf(fd, "         help: print this help\n");
@@ -167,7 +189,6 @@
     RESET_CONFIG_O(lockout);
     RESET_CONFIG_O(operation_authenticate_fails);
     RESET_CONFIG_O(operation_detect_interaction_fails);
-    RESET_CONFIG_O(operation_enroll_fails);
     RESET_CONFIG_V(operation_authenticate_latency);
     RESET_CONFIG_V(operation_detect_interaction_latency);
     RESET_CONFIG_V(operation_enroll_latency);
diff --git a/biometrics/face/aidl/default/Face.h b/biometrics/face/aidl/default/Face.h
index 93fddb0..dbe6341 100644
--- a/biometrics/face/aidl/default/Face.h
+++ b/biometrics/face/aidl/default/Face.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <aidl/android/hardware/biometrics/face/BnFace.h>
+#include "FaceConfig.h"
 #include "Session.h"
 
 namespace aidl::android::hardware::biometrics::face {
@@ -33,9 +34,20 @@
     binder_status_t dump(int fd, const char** args, uint32_t numArgs);
     binder_status_t handleShellCommand(int in, int out, int err, const char** argv, uint32_t argc);
 
+    static FaceConfig& cfg() {
+        static FaceConfig* cfg = nullptr;
+        if (cfg == nullptr) {
+            cfg = new FaceConfig();
+            cfg->init();
+        }
+        return *cfg;
+    }
+    void resetConfigToDefault();
+    static const char* type2String(FaceSensorType type);
+    static const char* strength2String(common::SensorStrength strength);
+
   private:
     std::shared_ptr<Session> mSession;
-    void resetConfigToDefault();
     void onHelp(int);
 };
 
diff --git a/biometrics/face/aidl/default/FaceConfig.cpp b/biometrics/face/aidl/default/FaceConfig.cpp
new file mode 100644
index 0000000..a91d7cc
--- /dev/null
+++ b/biometrics/face/aidl/default/FaceConfig.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "FaceConfig"
+
+#include "FaceConfig.h"
+
+#include <android-base/logging.h>
+
+#include <face.sysprop.h>
+
+using namespace ::android::face::virt;
+
+namespace aidl::android::hardware::biometrics::face {
+
+// Wrapper to system property access functions
+#define CREATE_GETTER_SETTER_WRAPPER(_NAME_, _T_)           \
+    ConfigValue _NAME_##Getter() {                          \
+        return FaceHalProperties::_NAME_();                 \
+    }                                                       \
+    bool _NAME_##Setter(const ConfigValue& v) {             \
+        return FaceHalProperties::_NAME_(std::get<_T_>(v)); \
+    }
+
+CREATE_GETTER_SETTER_WRAPPER(type, OptString)
+CREATE_GETTER_SETTER_WRAPPER(enrollments, OptIntVec)
+CREATE_GETTER_SETTER_WRAPPER(enrollment_hit, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(next_enrollment, OptString)
+CREATE_GETTER_SETTER_WRAPPER(authenticator_id, OptInt64)
+CREATE_GETTER_SETTER_WRAPPER(challenge, OptInt64)
+CREATE_GETTER_SETTER_WRAPPER(strength, OptString)
+CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_fails, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_latency, OptIntVec)
+CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_duration, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_error, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_acquired, OptString)
+CREATE_GETTER_SETTER_WRAPPER(operation_enroll_latency, OptIntVec)
+CREATE_GETTER_SETTER_WRAPPER(operation_detect_interaction_fails, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(operation_detect_interaction_latency, OptIntVec)
+CREATE_GETTER_SETTER_WRAPPER(lockout, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(lockout_enable, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(lockout_timed_enable, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(lockout_timed_threshold, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(lockout_timed_duration, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(lockout_permanent_threshold, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(features, OptIntVec)
+
+// Name, Getter, Setter, Parser and default value
+#define NGS(_NAME_) #_NAME_, _NAME_##Getter, _NAME_##Setter
+static Config::Data configData[] = {
+        {NGS(type), &Config::parseString, "rgb"},
+        {NGS(enrollments), &Config::parseIntVec, ""},
+        {NGS(enrollment_hit), &Config::parseInt32, "0"},
+        {NGS(next_enrollment), &Config::parseString,
+         "1:1000-[21,7,1,1103],1500-[1108,1],2000-[1113,1],2500-[1118,1]:true"},
+        {NGS(authenticator_id), &Config::parseInt64, "0"},
+        {NGS(challenge), &Config::parseInt64, ""},
+        {NGS(strength), &Config::parseString, "strong"},
+        {NGS(operation_authenticate_fails), &Config::parseBool, "false"},
+        {NGS(operation_authenticate_latency), &Config::parseIntVec, ""},
+        {NGS(operation_authenticate_duration), &Config::parseInt32, "500"},
+        {NGS(operation_authenticate_error), &Config::parseInt32, "0"},
+        {NGS(operation_authenticate_acquired), &Config::parseString, ""},
+        {NGS(operation_enroll_latency), &Config::parseIntVec, ""},
+        {NGS(operation_detect_interaction_latency), &Config::parseIntVec, ""},
+        {NGS(operation_detect_interaction_fails), &Config::parseBool, "false"},
+        {NGS(lockout), &Config::parseBool, "false"},
+        {NGS(lockout_enable), &Config::parseBool, "false"},
+        {NGS(lockout_timed_enable), &Config::parseBool, "false"},
+        {NGS(lockout_timed_threshold), &Config::parseInt32, "3"},
+        {NGS(lockout_timed_duration), &Config::parseInt32, "10000"},
+        {NGS(lockout_permanent_threshold), &Config::parseInt32, "5"},
+        {NGS(features), &Config::parseIntVec, ""}};
+
+Config::Data* FaceConfig::getConfigData(int* size) {
+    *size = sizeof(configData) / sizeof(configData[0]);
+    return configData;
+}
+
+}  // namespace aidl::android::hardware::biometrics::face
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl b/biometrics/face/aidl/default/FaceConfig.h
similarity index 64%
copy from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
copy to biometrics/face/aidl/default/FaceConfig.h
index 4298ba9..64b62e0 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
+++ b/biometrics/face/aidl/default/FaceConfig.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -13,13 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.hardware.security.see.hwcrypto.types;
 
-import android.hardware.security.see.hwcrypto.types.AesKey;
+#pragma once
 
-/*
- * Type encapsulating a clear key.
- */
-union ExplicitKeyMaterial {
-    AesKey aes;
-}
+#include "config/Config.h"
+
+namespace aidl::android::hardware::biometrics::face {
+
+class FaceConfig : public Config {
+    Config::Data* getConfigData(int* size) override;
+};
+
+}  // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/FakeFaceEngine.cpp b/biometrics/face/aidl/default/FakeFaceEngine.cpp
index bf75874..70d9f2d 100644
--- a/biometrics/face/aidl/default/FakeFaceEngine.cpp
+++ b/biometrics/face/aidl/default/FakeFaceEngine.cpp
@@ -23,6 +23,7 @@
 
 #include <face.sysprop.h>
 
+#include "Face.h"
 #include "util/CancellationSignal.h"
 #include "util/Util.h"
 
@@ -31,23 +32,23 @@
 namespace aidl::android::hardware::biometrics::face {
 
 FaceSensorType FakeFaceEngine::GetSensorType() {
-    std::string type = FaceHalProperties::type().value_or("");
+    std::string type = Face::cfg().get<std::string>("type");
     if (type == "IR") {
         return FaceSensorType::IR;
     } else {
-        FaceHalProperties::type("RGB");
+        Face::cfg().set<std::string>("type", "RGB");
         return FaceSensorType::RGB;
     }
 }
 
 common::SensorStrength FakeFaceEngine::GetSensorStrength() {
-    std::string strength = FaceHalProperties::strength().value_or("");
+    std::string strength = Face::cfg().get<std::string>("strength");
     if (strength == "convenience") {
         return common::SensorStrength::CONVENIENCE;
     } else if (strength == "weak") {
         return common::SensorStrength::WEAK;
     } else {
-        FaceHalProperties::strength("strong");
+        // Face::cfg().set<std::string>("strength", "strong");
         return common::SensorStrength::STRONG;
     }
 }
@@ -56,13 +57,13 @@
     BEGIN_OP(0);
     std::uniform_int_distribution<int64_t> dist;
     auto challenge = dist(mRandom);
-    FaceHalProperties::challenge(challenge);
+    Face::cfg().set<int64_t>("challenge", challenge);
     cb->onChallengeGenerated(challenge);
 }
 
 void FakeFaceEngine::revokeChallengeImpl(ISessionCallback* cb, int64_t challenge) {
     BEGIN_OP(0);
-    FaceHalProperties::challenge({});
+    Face::cfg().set<int64_t>("challenge", 0);
     cb->onChallengeRevoked(challenge);
 }
 void FakeFaceEngine::getEnrollmentConfigImpl(ISessionCallback* /*cb*/,
@@ -71,7 +72,7 @@
                                 EnrollmentType /*enrollmentType*/,
                                 const std::vector<Feature>& /*features*/,
                                 const std::future<void>& cancel) {
-    BEGIN_OP(getLatency(FaceHalProperties::operation_enroll_latency()));
+    BEGIN_OP(getLatency(Face::cfg().getopt<OptIntVec>("operation_enroll_latency")));
 
     // Do proper HAT verification in the real implementation.
     if (hat.mac.empty()) {
@@ -80,18 +81,19 @@
         return;
     }
 
-    // Format: <id>:<progress_ms-[acquiredInfo,...],...:<success>
-    // ------:-----------------------------------------:--------------
-    //          |           |                              |--->enrollment success (true/false)
-    //          |           |--> progress_steps
+    // Format:
+    //    <id>:<progress_ms-[acquiredInfo,...],...:<success>
+    //    -------:--------------------------------------------------:--------------
+    //          |           |                                                   |--->enrollment
+    //          success (true/false) |           |--> progress_steps
     //          |
     //          |-->enrollment id
     //
     //
-    //   progress_steps
+    //   progress_steps:
     //        <progress_duration>-[acquiredInfo,...]+
     //        ----------------------------  ---------------------
-    //                 |                            |-> sequence of acquiredInfo code
+    //                 |                              |-> sequence of acquiredInfo code
     //                 | --> time duration of the step in ms
     //
     //        E.g.   1:2000-[21,1108,5,6,1],1000-[1113,4,1]:true
@@ -101,7 +103,7 @@
     //
     std::string defaultNextEnrollment =
             "1:1000-[21,7,1,1103],1500-[1108,1],2000-[1113,1],2500-[1118,1]:true";
-    auto nextEnroll = FaceHalProperties::next_enrollment().value_or(defaultNextEnrollment);
+    auto nextEnroll = Face::cfg().get<std::string>("next_enrollment");
     auto parts = Util::split(nextEnroll, ":");
     if (parts.size() != 3) {
         LOG(ERROR) << "Fail: invalid next_enrollment:" << nextEnroll;
@@ -137,19 +139,19 @@
 
         if (left == 0 && !IS_TRUE(parts[2])) {  // end and failed
             LOG(ERROR) << "Fail: requested by caller: " << nextEnroll;
-            FaceHalProperties::next_enrollment({});
+            Face::cfg().setopt<OptString>("next_enrollment", std::nullopt);
             cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
         } else {  // progress and update props if last time
             LOG(INFO) << "onEnroll: " << enrollmentId << " left: " << left;
             if (left == 0) {
-                auto enrollments = FaceHalProperties::enrollments();
+                auto enrollments = Face::cfg().getopt<OptIntVec>("enrollments");
                 enrollments.emplace_back(enrollmentId);
-                FaceHalProperties::enrollments(enrollments);
-                FaceHalProperties::next_enrollment({});
+                Face::cfg().setopt<OptIntVec>("enrollments", enrollments);
+                Face::cfg().setopt<OptString>("next_enrollment", std::nullopt);
                 // change authenticatorId after new enrollment
-                auto id = FaceHalProperties::authenticator_id().value_or(0);
+                auto id = Face::cfg().get<std::int64_t>("authenticator_id");
                 auto newId = id + 1;
-                FaceHalProperties::authenticator_id(newId);
+                Face::cfg().set<std::int64_t>("authenticator_id", newId);
                 LOG(INFO) << "Enrolled: " << enrollmentId;
             }
             cb->onEnrollmentProgress(enrollmentId, left);
@@ -159,10 +161,12 @@
 
 void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationId*/,
                                       const std::future<void>& cancel) {
-    BEGIN_OP(getLatency(FaceHalProperties::operation_authenticate_latency()));
+    BEGIN_OP(getLatency(Face::cfg().getopt<OptIntVec>("operation_authenticate_latency")));
 
-    auto id = FaceHalProperties::enrollment_hit().value_or(0);
-    auto enrolls = FaceHalProperties::enrollments();
+    // SLEEP_MS(3000);  //emulate hw HAL
+
+    auto id = Face::cfg().get<std::int32_t>("enrollment_hit");
+    auto enrolls = Face::cfg().getopt<OptIntVec>("enrollments");
     auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
 
     auto vec2str = [](std::vector<AcquiredInfo> va) {
@@ -192,10 +196,12 @@
     }
 
     int64_t now = Util::getSystemNanoTime();
-    int64_t duration =
-            FaceHalProperties::operation_authenticate_duration().value_or(defaultAuthDuration);
-    auto acquired =
-            FaceHalProperties::operation_authenticate_acquired().value_or(defaultAcquiredInfo);
+    int64_t duration = Face::cfg().get<std::int32_t>("operation_authenticate_duration");
+    auto acquired = Face::cfg().get<std::string>("operation_authenticate_acquired");
+    if (acquired.empty()) {
+        Face::cfg().set<std::string>("operation_authenticate_acquired", defaultAcquiredInfo);
+        acquired = defaultAcquiredInfo;
+    }
     auto acquiredInfos = Util::parseIntSequence(acquired);
     int N = acquiredInfos.size();
 
@@ -211,21 +217,21 @@
 
     int i = 0;
     do {
-        if (FaceHalProperties::lockout().value_or(false)) {
+        if (Face::cfg().get<bool>("lockout")) {
             LOG(ERROR) << "Fail: lockout";
             cb->onLockoutPermanent();
             cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
             return;
         }
 
-        if (FaceHalProperties::operation_authenticate_fails().value_or(false)) {
+        if (Face::cfg().get<bool>("operation_authenticate_fails")) {
             LOG(ERROR) << "Fail: operation_authenticate_fails";
             mLockoutTracker.addFailedAttempt(cb);
             cb->onAuthenticationFailed();
             return;
         }
 
-        auto err = FaceHalProperties::operation_authenticate_error().value_or(0);
+        auto err = Face::cfg().get<std::int32_t>("operation_authenticate_error");
         if (err != 0) {
             LOG(ERROR) << "Fail: operation_authenticate_error";
             auto ec = convertError(err);
@@ -249,6 +255,15 @@
             LOG(INFO) << "AcquiredInfo:" << i << ": (" << (int)ac.first << "," << (int)ac.second
                       << ")";
             i++;
+
+            // the captured face id may change during authentication period
+            auto idnew = Face::cfg().get<std::int32_t>("enrollment_hit");
+            if (id != idnew) {
+                isEnrolled = std::find(enrolls.begin(), enrolls.end(), idnew) != enrolls.end();
+                LOG(INFO) << "enrollment_hit changed from " << id << " to " << idnew;
+                id = idnew;
+                break;
+            }
         }
 
         SLEEP_MS(duration / N);
@@ -292,9 +307,9 @@
 }
 
 void FakeFaceEngine::detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel) {
-    BEGIN_OP(getLatency(FaceHalProperties::operation_detect_interaction_latency()));
+    BEGIN_OP(getLatency(Face::cfg().getopt<OptIntVec>("operation_detect_interaction_latency")));
 
-    if (FaceHalProperties::operation_detect_interaction_fails().value_or(false)) {
+    if (Face::cfg().get<bool>("operation_detect_interaction_fails")) {
         LOG(ERROR) << "Fail: operation_detect_interaction_fails";
         cb->onError(Error::VENDOR, 0 /* vendorError */);
         return;
@@ -306,8 +321,8 @@
         return;
     }
 
-    auto id = FaceHalProperties::enrollment_hit().value_or(0);
-    auto enrolls = FaceHalProperties::enrollments();
+    auto id = Face::cfg().get<std::int32_t>("enrollment_hit");
+    auto enrolls = Face::cfg().getopt<OptIntVec>("enrollments");
     auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
     if (id <= 0 || !isEnrolled) {
         LOG(ERROR) << "Fail: not enrolled";
@@ -321,7 +336,7 @@
 void FakeFaceEngine::enumerateEnrollmentsImpl(ISessionCallback* cb) {
     BEGIN_OP(0);
     std::vector<int32_t> enrollments;
-    for (const auto& enrollmentId : FaceHalProperties::enrollments()) {
+    for (const auto& enrollmentId : Face::cfg().getopt<OptIntVec>("enrollments")) {
         if (enrollmentId) {
             enrollments.push_back(*enrollmentId);
         }
@@ -334,20 +349,20 @@
     BEGIN_OP(0);
 
     std::vector<std::optional<int32_t>> newEnrollments;
-    for (const auto& enrollment : FaceHalProperties::enrollments()) {
+    for (const auto& enrollment : Face::cfg().getopt<OptIntVec>("enrollments")) {
         auto id = enrollment.value_or(0);
         if (std::find(enrollmentIds.begin(), enrollmentIds.end(), id) == enrollmentIds.end()) {
             newEnrollments.emplace_back(id);
         }
     }
-    FaceHalProperties::enrollments(newEnrollments);
+    Face::cfg().setopt<OptIntVec>("enrollments", newEnrollments);
     cb->onEnrollmentsRemoved(enrollmentIds);
 }
 
 void FakeFaceEngine::getFeaturesImpl(ISessionCallback* cb) {
     BEGIN_OP(0);
 
-    if (FaceHalProperties::enrollments().empty()) {
+    if (Face::cfg().getopt<OptIntVec>("enrollments").empty()) {
         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
         return;
     }
@@ -365,7 +380,7 @@
                                     Feature feature, bool enabled) {
     BEGIN_OP(0);
 
-    if (FaceHalProperties::enrollments().empty()) {
+    if (Face::cfg().getopt<OptIntVec>("enrollments").empty()) {
         LOG(ERROR) << "Unable to set feature, enrollments are empty";
         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
         return;
@@ -377,7 +392,7 @@
         return;
     }
 
-    auto features = FaceHalProperties::features();
+    auto features = Face::cfg().getopt<OptIntVec>("features");
 
     auto itr = std::find_if(features.begin(), features.end(), [feature](const auto& theFeature) {
         return *theFeature == (int)feature;
@@ -389,7 +404,7 @@
         features.push_back((int)feature);
     }
 
-    FaceHalProperties::features(features);
+    Face::cfg().setopt<OptIntVec>("features", features);
     cb->onFeatureSet(feature);
 }
 
@@ -399,22 +414,22 @@
     if (GetSensorStrength() != common::SensorStrength::STRONG) {
         cb->onAuthenticatorIdRetrieved(0);
     } else {
-        cb->onAuthenticatorIdRetrieved(FaceHalProperties::authenticator_id().value_or(0));
+        cb->onAuthenticatorIdRetrieved(Face::cfg().get<std::int64_t>("authenticator_id"));
     }
 }
 
 void FakeFaceEngine::invalidateAuthenticatorIdImpl(ISessionCallback* cb) {
     BEGIN_OP(0);
-    int64_t authenticatorId = FaceHalProperties::authenticator_id().value_or(0);
+    int64_t authenticatorId = Face::cfg().get<std::int64_t>("authenticator_id");
     int64_t newId = authenticatorId + 1;
-    FaceHalProperties::authenticator_id(newId);
+    Face::cfg().set<std::int64_t>("authenticator_id", newId);
     cb->onAuthenticatorIdInvalidated(newId);
 }
 
 void FakeFaceEngine::resetLockoutImpl(ISessionCallback* cb,
                                       const keymaster::HardwareAuthToken& /*hat*/) {
     BEGIN_OP(0);
-    FaceHalProperties::lockout(false);
+    Face::cfg().set<bool>("lockout", false);
     mLockoutTracker.reset();
     cb->onLockoutCleared();
 }
diff --git a/biometrics/face/aidl/default/FakeLockoutTracker.cpp b/biometrics/face/aidl/default/FakeLockoutTracker.cpp
index 70bf08e..35d7c28 100644
--- a/biometrics/face/aidl/default/FakeLockoutTracker.cpp
+++ b/biometrics/face/aidl/default/FakeLockoutTracker.cpp
@@ -19,6 +19,7 @@
 #include "FakeLockoutTracker.h"
 #include <android-base/logging.h>
 #include <face.sysprop.h>
+#include "Face.h"
 #include "util/Util.h"
 
 using namespace ::android::face::virt;
@@ -36,15 +37,15 @@
 }
 
 void FakeLockoutTracker::addFailedAttempt(ISessionCallback* cb) {
-    bool lockoutEnabled = FaceHalProperties::lockout_enable().value_or(false);
-    bool timedLockoutenabled = FaceHalProperties::lockout_timed_enable().value_or(false);
+    bool lockoutEnabled = Face::cfg().get<bool>("lockout_enable");
+    bool timedLockoutenabled = Face::cfg().get<bool>("lockout_timed_enable");
     if (lockoutEnabled) {
         mFailedCount++;
         mTimedFailedCount++;
         mLastFailedTime = Util::getSystemNanoTime();
-        int32_t lockoutTimedThreshold = FaceHalProperties::lockout_timed_threshold().value_or(3);
+        int32_t lockoutTimedThreshold = Face::cfg().get<std::int32_t>("lockout_timed_threshold");
         int32_t lockoutPermanetThreshold =
-                FaceHalProperties::lockout_permanent_threshold().value_or(5);
+                Face::cfg().get<std::int32_t>("lockout_permanent_threshold");
         if (mFailedCount >= lockoutPermanetThreshold) {
             mCurrentMode = LockoutMode::kPermanent;
             LOG(ERROR) << "FakeLockoutTracker: lockoutPermanent";
@@ -68,7 +69,7 @@
 }
 
 int32_t FakeLockoutTracker::getTimedLockoutDuration() {
-    return FaceHalProperties::lockout_timed_duration().value_or(10 * 1000);
+    return Face::cfg().get<std::int32_t>("lockout_timed_duration");
 }
 
 int64_t FakeLockoutTracker::getLockoutTimeLeft() {
diff --git a/biometrics/face/aidl/default/VirtualHal.cpp b/biometrics/face/aidl/default/VirtualHal.cpp
new file mode 100644
index 0000000..52ac23b
--- /dev/null
+++ b/biometrics/face/aidl/default/VirtualHal.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2024 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 <unordered_map>
+
+#include "VirtualHal.h"
+
+#include <android-base/logging.h>
+
+#include "util/CancellationSignal.h"
+
+#undef LOG_TAG
+#define LOG_TAG "FaceVirtualHalAidl"
+
+namespace aidl::android::hardware::biometrics::face {
+using AcquiredInfoAndVendorCode = virtualhal::AcquiredInfoAndVendorCode;
+using Tag = AcquiredInfoAndVendorCode::Tag;
+
+::ndk::ScopedAStatus VirtualHal::setEnrollments(const std::vector<int32_t>& enrollments) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().setopt<OptIntVec>("enrollments", intVec2OptIntVec(enrollments));
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setEnrollmentHit(int32_t enrollment_hit) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<std::int32_t>("enrollment_hit", enrollment_hit);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setNextEnrollment(
+        const ::aidl::android::hardware::biometrics::face::NextEnrollment& next_enrollment) {
+    Face::cfg().sourcedFromAidl();
+    std::ostringstream os;
+    os << next_enrollment.id << ":";
+
+    int stepSize = next_enrollment.progressSteps.size();
+    for (int i = 0; i < stepSize; i++) {
+        auto& step = next_enrollment.progressSteps[i];
+        os << step.durationMs;
+        int acSize = step.acquiredInfoAndVendorCodes.size();
+        for (int j = 0; j < acSize; j++) {
+            if (j == 0) os << "-[";
+            auto& acquiredInfoAndVendorCode = step.acquiredInfoAndVendorCodes[j];
+            if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::vendorCode)
+                os << acquiredInfoAndVendorCode.get<Tag::vendorCode>();
+            else if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
+                os << (int)acquiredInfoAndVendorCode.get<Tag::acquiredInfo>();
+            else
+                LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode union tag";
+            if (j == acSize - 1)
+                os << "]";
+            else
+                os << ",";
+        }
+        if (i == stepSize - 1)
+            os << ":";
+        else
+            os << ",";
+    }
+
+    os << (next_enrollment.result ? "true" : "false");
+    Face::cfg().set<std::string>("next_enrollment", os.str());
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setAuthenticatorId(int64_t in_id) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<int64_t>("authenticator_id", in_id);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setChallenge(int64_t in_challenge) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<int64_t>("challenge", in_challenge);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateFails(bool in_fail) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<bool>("operation_authenticate_fails", in_fail);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateLatency(
+        const std::vector<int32_t>& in_latency) {
+    ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
+    if (!status.isOk()) {
+        return status;
+    }
+
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().setopt<OptIntVec>("operation_authenticate_latency", intVec2OptIntVec(in_latency));
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateDuration(int32_t in_duration) {
+    if (in_duration < 0) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
+    }
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<int32_t>("operation_authenticate_duration", in_duration);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateError(int32_t in_error) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<int32_t>("operation_authenticate_error", in_error);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateAcquired(
+        const std::vector<AcquiredInfoAndVendorCode>& in_acquired) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().setopt<OptIntVec>("operation_authenticate_acquired",
+                                  acquiredInfoVec2OptIntVec(in_acquired));
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationEnrollLatency(const std::vector<int32_t>& in_latency) {
+    ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
+    if (!status.isOk()) {
+        return status;
+    }
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().setopt<OptIntVec>("operation_enroll_latency", intVec2OptIntVec(in_latency));
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionLatency(
+        const std::vector<int32_t>& in_latency) {
+    ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
+    if (!status.isOk()) {
+        return status;
+    }
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().setopt<OptIntVec>("operation_detect_interact_latency",
+                                  intVec2OptIntVec(in_latency));
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionFails(bool in_fails) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<bool>("operation_detect_interaction_fails", in_fails);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setLockout(bool in_lockout) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<bool>("lockout", in_lockout);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setLockoutEnable(bool in_enable) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<bool>("lockout_enable", in_enable);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setLockoutTimedEnable(bool in_enable) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<bool>("lockout_timed_enable", in_enable);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setLockoutTimedThreshold(int32_t in_threshold) {
+    if (in_threshold < 0) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative"));
+    }
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<int32_t>("lockout_timed_threshold", in_threshold);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setLockoutTimedDuration(int32_t in_duration) {
+    if (in_duration < 0) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
+    }
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<int32_t>("lockout_timed_duration", in_duration);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setLockoutPermanentThreshold(int32_t in_threshold) {
+    if (in_threshold < 0) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative"));
+    }
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<int32_t>("lockout_permanent_threshold", in_threshold);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::resetConfigurations() {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().init();
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setType(
+        ::aidl::android::hardware::biometrics::face::FaceSensorType in_type) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<std::string>("type", Face::type2String(in_type));
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::setSensorStrength(common::SensorStrength in_strength) {
+    Face::cfg().sourcedFromAidl();
+    Face::cfg().set<std::string>("strength", Face::strength2String(in_strength));
+    return ndk::ScopedAStatus::ok();
+}
+
+OptIntVec VirtualHal::intVec2OptIntVec(const std::vector<int32_t>& in_vec) {
+    OptIntVec optIntVec;
+    std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
+                   [](int value) { return std::optional<int>(value); });
+    return optIntVec;
+}
+
+OptIntVec VirtualHal::acquiredInfoVec2OptIntVec(
+        const std::vector<AcquiredInfoAndVendorCode>& in_vec) {
+    OptIntVec optIntVec;
+    std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
+                   [](AcquiredInfoAndVendorCode ac) {
+                       int value;
+                       if (ac.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
+                           value = (int)ac.get<Tag::acquiredInfo>();
+                       else if (ac.getTag() == AcquiredInfoAndVendorCode::vendorCode)
+                           value = ac.get<Tag::vendorCode>();
+                       else
+                           LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode tag";
+                       return std::optional<int>(value);
+                   });
+    return optIntVec;
+}
+
+::ndk::ScopedAStatus VirtualHal::sanityCheckLatency(const std::vector<int32_t>& in_latency) {
+    if (in_latency.size() == 0 || in_latency.size() > 2) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IVirtualHal::STATUS_INVALID_PARAMETER,
+                "Error: input input array must contain 1 or 2 elements"));
+    }
+
+    for (auto x : in_latency) {
+        if (x < 0) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IVirtualHal::STATUS_INVALID_PARAMETER,
+                    "Error: input data must not be negative"));
+        }
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus VirtualHal::getFaceHal(std::shared_ptr<IFace>* pFace) {
+    *pFace = mFp;
+    return ndk::ScopedAStatus::ok();
+}
+}  // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/VirtualHal.h b/biometrics/face/aidl/default/VirtualHal.h
new file mode 100644
index 0000000..f2ac552
--- /dev/null
+++ b/biometrics/face/aidl/default/VirtualHal.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/biometrics/face/virtualhal/BnVirtualHal.h>
+
+#include "Face.h"
+
+namespace aidl::android::hardware::biometrics::face {
+using namespace virtualhal;
+class VirtualHal : public BnVirtualHal {
+  public:
+    VirtualHal(std::shared_ptr<Face> fp) : mFp(fp) {}
+
+    ::ndk::ScopedAStatus setEnrollments(const std::vector<int32_t>& in_id) override;
+    ::ndk::ScopedAStatus setEnrollmentHit(int32_t in_hit_id) override;
+    ::ndk::ScopedAStatus setNextEnrollment(
+            const ::aidl::android::hardware::biometrics::face::NextEnrollment& in_next_enrollment)
+            override;
+    ::ndk::ScopedAStatus setAuthenticatorId(int64_t in_id) override;
+    ::ndk::ScopedAStatus setChallenge(int64_t in_challenge) override;
+    ::ndk::ScopedAStatus setOperationAuthenticateFails(bool in_fail) override;
+    ::ndk::ScopedAStatus setOperationAuthenticateLatency(
+            const std::vector<int32_t>& in_latency) override;
+    ::ndk::ScopedAStatus setOperationAuthenticateDuration(int32_t in_duration) override;
+    ::ndk::ScopedAStatus setOperationAuthenticateError(int32_t in_error) override;
+    ::ndk::ScopedAStatus setOperationAuthenticateAcquired(
+            const std::vector<AcquiredInfoAndVendorCode>& in_acquired) override;
+    ::ndk::ScopedAStatus setOperationEnrollLatency(const std::vector<int32_t>& in_latency) override;
+    ::ndk::ScopedAStatus setOperationDetectInteractionLatency(
+            const std::vector<int32_t>& in_latency) override;
+    ::ndk::ScopedAStatus setOperationDetectInteractionFails(bool in_fails) override;
+    ::ndk::ScopedAStatus setLockout(bool in_lockout) override;
+    ::ndk::ScopedAStatus setLockoutEnable(bool in_enable) override;
+    ::ndk::ScopedAStatus setLockoutTimedEnable(bool in_enable) override;
+    ::ndk::ScopedAStatus setLockoutTimedThreshold(int32_t in_threshold) override;
+    ::ndk::ScopedAStatus setLockoutTimedDuration(int32_t in_duration) override;
+    ::ndk::ScopedAStatus setLockoutPermanentThreshold(int32_t in_threshold) override;
+    ::ndk::ScopedAStatus resetConfigurations() override;
+    ::ndk::ScopedAStatus setType(
+            ::aidl::android::hardware::biometrics::face::FaceSensorType in_type) override;
+    ::ndk::ScopedAStatus setSensorStrength(common::SensorStrength in_strength) override;
+    ::ndk::ScopedAStatus getFaceHal(std::shared_ptr<IFace>* _aidl_return);
+
+  private:
+    OptIntVec intVec2OptIntVec(const std::vector<int32_t>& intVec);
+    OptIntVec acquiredInfoVec2OptIntVec(const std::vector<AcquiredInfoAndVendorCode>& intVec);
+    ::ndk::ScopedAStatus sanityCheckLatency(const std::vector<int32_t>& in_latency);
+    std::shared_ptr<Face> mFp;
+};
+
+}  // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/apex/Android.bp b/biometrics/face/aidl/default/apex/Android.bp
index 86c4e12..0561145 100644
--- a/biometrics/face/aidl/default/apex/Android.bp
+++ b/biometrics/face/aidl/default/apex/Android.bp
@@ -19,11 +19,11 @@
 apex {
     name: "com.android.hardware.biometrics.face.virtual",
     manifest: "manifest.json",
-    file_contexts: "file_contexts",
+    file_contexts: ":com.android.biometrics.virtual.face-file_contexts",
     key: "com.android.hardware.key",
     certificate: ":com.android.hardware.certificate",
     updatable: false,
-    vendor: true,
+    system_ext_specific: true,
 
     binaries: [
         // hal
@@ -31,9 +31,7 @@
     ],
     prebuilts: [
         // init_rc
-        "face-example-apex.rc",
-        // vintf_fragment
-        "face-example-apex.xml",
+        "face-virtual-apex.rc",
     ],
 
     overrides: [
@@ -42,21 +40,7 @@
 }
 
 prebuilt_etc {
-    name: "face-example-apex.rc",
-    src: ":gen-face-example-apex.rc",
-    installable: false,
-}
-
-genrule {
-    name: "gen-face-example-apex.rc",
-    srcs: [":face-example.rc"],
-    out: ["face-example-apex.rc"],
-    cmd: "sed -e 's@/vendor/bin/@/apex/com.android.hardware.biometrics.face.virtual/bin/@' $(in) > $(out)",
-}
-
-prebuilt_etc {
-    name: "face-example-apex.xml",
-    src: ":face-example.xml",
-    sub_dir: "vintf",
+    name: "face-virtual-apex.rc",
+    src: ":face-virtual.rc",
     installable: false,
 }
diff --git a/biometrics/face/aidl/default/apex/file_contexts b/biometrics/face/aidl/default/apex/file_contexts
deleted file mode 100644
index 4f935c1..0000000
--- a/biometrics/face/aidl/default/apex/file_contexts
+++ /dev/null
@@ -1,3 +0,0 @@
-(/.*)?                                          u:object_r:vendor_file:s0
-/etc(/.*)?                                      u:object_r:vendor_configs_file:s0
-/bin/hw/android\.hardware\.biometrics\.face-service\.example u:object_r:hal_face_default_exec:s0
\ No newline at end of file
diff --git a/biometrics/face/aidl/default/api/android.hardware.biometrics.face.VirtualProps-current.txt b/biometrics/face/aidl/default/api/android.hardware.biometrics.face.VirtualProps-current.txt
index e69de29..6ad579c 100644
--- a/biometrics/face/aidl/default/api/android.hardware.biometrics.face.VirtualProps-current.txt
+++ b/biometrics/face/aidl/default/api/android.hardware.biometrics.face.VirtualProps-current.txt
@@ -0,0 +1,133 @@
+props {
+  owner: Vendor
+  module: "android.face.virt.FaceHalProperties"
+  prop {
+    api_name: "authenticator_id"
+    type: Long
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.authenticator_id"
+  }
+  prop {
+    api_name: "challenge"
+    type: Long
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.challenge"
+  }
+  prop {
+    api_name: "enrollment_hit"
+    type: Integer
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.enrollment_hit"
+  }
+  prop {
+    api_name: "enrollments"
+    type: IntegerList
+    access: ReadWrite
+    prop_name: "persist.vendor.face.virtual.enrollments"
+  }
+  prop {
+    api_name: "features"
+    type: IntegerList
+    access: ReadWrite
+    prop_name: "persist.vendor.face.virtual.features"
+  }
+  prop {
+    api_name: "lockout"
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.lockout"
+  }
+  prop {
+    api_name: "lockout_enable"
+    access: ReadWrite
+    prop_name: "persist.vendor.face.virtual.lockout_enable"
+  }
+  prop {
+    api_name: "lockout_permanent_threshold"
+    type: Integer
+    access: ReadWrite
+    prop_name: "persist.vendor.face.virtual.lockout_permanent_threshold"
+  }
+  prop {
+    api_name: "lockout_timed_duration"
+    type: Integer
+    access: ReadWrite
+    prop_name: "persist.vendor.face.virtual.lockout_timed_duration"
+  }
+  prop {
+    api_name: "lockout_timed_enable"
+    access: ReadWrite
+    prop_name: "persist.vendor.face.virtual.lockout_timed_enable"
+  }
+  prop {
+    api_name: "lockout_timed_threshold"
+    type: Integer
+    access: ReadWrite
+    prop_name: "persist.vendor.face.virtual.lockout_timed_threshold"
+  }
+  prop {
+    api_name: "next_enrollment"
+    type: String
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.next_enrollment"
+  }
+  prop {
+    api_name: "operation_authenticate_acquired"
+    type: String
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.operation_authenticate_acquired"
+  }
+  prop {
+    api_name: "operation_authenticate_duration"
+    type: Integer
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.operation_authenticate_duration"
+  }
+  prop {
+    api_name: "operation_authenticate_error"
+    type: Integer
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.operation_authenticate_error"
+  }
+  prop {
+    api_name: "operation_authenticate_fails"
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.operation_authenticate_fails"
+  }
+  prop {
+    api_name: "operation_authenticate_latency"
+    type: IntegerList
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.operation_authenticate_latency"
+  }
+  prop {
+    api_name: "operation_detect_interaction_fails"
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.operation_detect_interaction_fails"
+  }
+  prop {
+    api_name: "operation_detect_interaction_latency"
+    type: IntegerList
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.operation_detect_interaction_latency"
+  }
+  prop {
+    api_name: "operation_enroll_latency"
+    type: IntegerList
+    access: ReadWrite
+    prop_name: "vendor.face.virtual.operation_enroll_latency"
+  }
+  prop {
+    api_name: "strength"
+    type: String
+    access: ReadWrite
+    prop_name: "persist.vendor.face.virtual.strength"
+    enum_values: "convenience|weak|strong"
+  }
+  prop {
+    api_name: "type"
+    type: String
+    access: ReadWrite
+    prop_name: "persist.vendor.face.virtual.type"
+    enum_values: "IR|RGB"
+  }
+}
diff --git a/biometrics/face/aidl/default/face-default.rc b/biometrics/face/aidl/default/face-default.rc
new file mode 100644
index 0000000..7ce4249
--- /dev/null
+++ b/biometrics/face/aidl/default/face-default.rc
@@ -0,0 +1,8 @@
+service vendor.face-default /vendor/bin/hw/android.hardware.biometrics.face-service.default default
+    class hal
+    user nobody
+    group nobody
+    interface aidl android.hardware.biometrics.face.IFace/default
+    oneshot
+    disabled
+
diff --git a/biometrics/face/aidl/default/face-example.xml b/biometrics/face/aidl/default/face-default.xml
similarity index 81%
rename from biometrics/face/aidl/default/face-example.xml
rename to biometrics/face/aidl/default/face-default.xml
index 2b39b3d..94569de 100644
--- a/biometrics/face/aidl/default/face-example.xml
+++ b/biometrics/face/aidl/default/face-default.xml
@@ -2,6 +2,6 @@
     <hal format="aidl">
         <name>android.hardware.biometrics.face</name>
         <version>4</version>
-        <fqname>IFace/virtual</fqname>
+        <fqname>IFace/default</fqname>
     </hal>
 </manifest>
diff --git a/biometrics/face/aidl/default/face-example.rc b/biometrics/face/aidl/default/face-example.rc
deleted file mode 100644
index b0d82c6..0000000
--- a/biometrics/face/aidl/default/face-example.rc
+++ /dev/null
@@ -1,8 +0,0 @@
-service vendor.face-example /vendor/bin/hw/android.hardware.biometrics.face-service.example
-    class hal
-    user nobody
-    group nobody
-    interface aidl android.hardware.biometrics.face.IFace/virtual
-    oneshot
-    disabled
-
diff --git a/biometrics/face/aidl/default/face-virtual.rc b/biometrics/face/aidl/default/face-virtual.rc
new file mode 100644
index 0000000..8fb0a7b
--- /dev/null
+++ b/biometrics/face/aidl/default/face-virtual.rc
@@ -0,0 +1,8 @@
+service face-virtual /apex/com.android.hardware.biometrics.face.virtual/bin/hw/android.hardware.biometrics.face-service.example virtual
+    class hal
+    user nobody
+    group nobody
+    interface aidl android.hardware.biometrics.face.virtualhal.IVirtualHal/virtual
+    oneshot
+    disabled
+
diff --git a/biometrics/face/aidl/default/face.sysprop b/biometrics/face/aidl/default/face.sysprop
index 997fd67..ec2b92b 100644
--- a/biometrics/face/aidl/default/face.sysprop
+++ b/biometrics/face/aidl/default/face.sysprop
@@ -7,7 +7,7 @@
 prop {
     prop_name: "persist.vendor.face.virtual.type"
     type: String
-    scope: Internal
+    scope: Public
     access: ReadWrite
     enum_values: "IR|RGB"
     api_name: "type"
@@ -17,7 +17,7 @@
 prop {
     prop_name: "persist.vendor.face.virtual.strength"
     type: String
-    scope: Internal
+    scope: Public
     access: ReadWrite
     enum_values: "convenience|weak|strong"
     api_name: "strength"
@@ -27,7 +27,7 @@
 prop {
     prop_name: "persist.vendor.face.virtual.enrollments"
     type: IntegerList
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "enrollments"
 }
@@ -36,7 +36,7 @@
 prop {
     prop_name: "persist.vendor.face.virtual.features"
     type: IntegerList
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "features"
 }
@@ -46,7 +46,7 @@
 prop {
     prop_name: "vendor.face.virtual.enrollment_hit"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "enrollment_hit"
 }
@@ -60,7 +60,7 @@
 prop {
     prop_name: "vendor.face.virtual.next_enrollment"
     type: String
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "next_enrollment"
 }
@@ -69,7 +69,7 @@
 prop {
     prop_name: "vendor.face.virtual.authenticator_id"
     type: Long
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "authenticator_id"
 }
@@ -78,7 +78,7 @@
 prop {
     prop_name: "vendor.face.virtual.challenge"
     type: Long
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "challenge"
 }
@@ -87,7 +87,7 @@
 prop {
     prop_name: "vendor.face.virtual.lockout"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "lockout"
 }
@@ -96,7 +96,7 @@
 prop {
     prop_name: "vendor.face.virtual.operation_authenticate_fails"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_authenticate_fails"
 }
@@ -105,27 +105,18 @@
 prop {
     prop_name: "vendor.face.virtual.operation_detect_interaction_fails"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_detect_interaction_fails"
 }
 
-# force all enroll operations to fail
-prop {
-    prop_name: "vendor.face.virtual.operation_enroll_fails"
-    type: Boolean
-    scope: Internal
-    access: ReadWrite
-    api_name: "operation_enroll_fails"
-}
-
 # add a latency to authentication operations
 # Note that this latency is the initial authentication latency that occurs before
 # the HAL will send AcquiredInfo::START and AcquiredInfo::FIRST_FRAME_RECEIVED
 prop {
     prop_name: "vendor.face.virtual.operation_authenticate_latency"
     type: IntegerList
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_authenticate_latency"
 }
@@ -134,7 +125,7 @@
 prop {
     prop_name: "vendor.face.virtual.operation_detect_interaction_latency"
     type: IntegerList
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_detect_interaction_latency"
 }
@@ -143,7 +134,7 @@
 prop {
     prop_name: "vendor.face.virtual.operation_enroll_latency"
     type: IntegerList
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_enroll_latency"
 }
@@ -153,7 +144,7 @@
 prop {
     prop_name: "vendor.face.virtual.operation_authenticate_duration"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_authenticate_duration"
 }
@@ -162,7 +153,7 @@
 prop {
     prop_name: "vendor.face.virtual.operation_authenticate_error"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_authenticate_error"
 }
@@ -171,7 +162,7 @@
 prop {
     prop_name: "vendor.face.virtual.operation_authenticate_acquired"
     type: String
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_authenticate_acquired"
 }
@@ -180,7 +171,7 @@
 prop {
     prop_name: "persist.vendor.face.virtual.lockout_enable"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "lockout_enable"
 }
@@ -189,7 +180,7 @@
 prop {
     prop_name: "persist.vendor.face.virtual.lockout_timed_enable"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "lockout_timed_enable"
 }
@@ -198,7 +189,7 @@
 prop {
     prop_name: "persist.vendor.face.virtual.lockout_timed_threshold"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "lockout_timed_threshold"
 }
@@ -207,7 +198,7 @@
 prop {
     prop_name: "persist.vendor.face.virtual.lockout_timed_duration"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "lockout_timed_duration"
 }
@@ -216,7 +207,7 @@
 prop {
     prop_name: "persist.vendor.face.virtual.lockout_permanent_threshold"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "lockout_permanent_threshold"
 }
diff --git a/biometrics/face/aidl/default/main.cpp b/biometrics/face/aidl/default/main.cpp
index 38e1c63..75a4479 100644
--- a/biometrics/face/aidl/default/main.cpp
+++ b/biometrics/face/aidl/default/main.cpp
@@ -14,25 +14,49 @@
  * limitations under the License.
  */
 
+#undef LOG_TAG
+#define LOG_TAG "FaceVirtualHal"
+
 #include "Face.h"
+#include "VirtualHal.h"
 
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
 using aidl::android::hardware::biometrics::face::Face;
+using aidl::android::hardware::biometrics::face::VirtualHal;
 
-int main() {
-    LOG(INFO) << "Face HAL started";
+int main(int argc, char** argv) {
+    if (argc < 2) {
+        LOG(ERROR) << "Missing argument -> exiting, Valid arguments:[default|virtual]";
+        return EXIT_FAILURE;
+    }
+    LOG(INFO) << "Face HAL started: " << argv[1];
     ABinderProcess_setThreadPoolMaxThreadCount(0);
     std::shared_ptr<Face> hal = ndk::SharedRefBase::make<Face>();
+    std::shared_ptr<VirtualHal> hal_vhal = ndk::SharedRefBase::make<VirtualHal>(hal);
 
-    const std::string instance = std::string(Face::descriptor) + "/virtual";
-    binder_status_t status =
-            AServiceManager_registerLazyService(hal->asBinder().get(), instance.c_str());
-    CHECK_EQ(status, STATUS_OK);
+    if (strcmp(argv[1], "default") == 0) {
+        const std::string instance = std::string(Face::descriptor) + "/default";
+        auto binder = hal->asBinder();
+        binder_status_t status =
+                AServiceManager_registerLazyService(binder.get(), instance.c_str());
+        CHECK_EQ(status, STATUS_OK);
+        LOG(INFO) << "started IFace/default";
+    } else if (strcmp(argv[1], "virtual") == 0) {
+        const std::string instance = std::string(VirtualHal::descriptor) + "/virtual";
+        auto binder = hal_vhal->asBinder();
+        binder_status_t status =
+                AServiceManager_registerLazyService(binder.get(), instance.c_str());
+        CHECK_EQ(status, STATUS_OK);
+        LOG(INFO) << "started IVirtualHal/virtual";
+    } else {
+        LOG(ERROR) << "Unexpected argument: " << argv[1];
+        return EXIT_FAILURE;
+    }
     AServiceManager_forceLazyServicesPersist(true);
 
     ABinderProcess_joinThreadPool();
-    return EXIT_FAILURE;  // should not reach
+    return EXIT_FAILURE;  // should not reach here
 }
diff --git a/biometrics/face/aidl/default/tests/FakeFaceEngineTest.cpp b/biometrics/face/aidl/default/tests/FakeFaceEngineTest.cpp
index 8c39b58..d448532 100644
--- a/biometrics/face/aidl/default/tests/FakeFaceEngineTest.cpp
+++ b/biometrics/face/aidl/default/tests/FakeFaceEngineTest.cpp
@@ -21,6 +21,7 @@
 #include <aidl/android/hardware/biometrics/face/BnSessionCallback.h>
 #include <android-base/logging.h>
 
+#include "Face.h"
 #include "FakeFaceEngine.h"
 #include "util/Util.h"
 
@@ -141,12 +142,12 @@
     }
 
     void TearDown() override {
-        FaceHalProperties::enrollments({});
-        FaceHalProperties::challenge({});
-        FaceHalProperties::features({});
-        FaceHalProperties::authenticator_id({});
-        FaceHalProperties::strength("");
-        FaceHalProperties::operation_detect_interaction_latency({});
+        Face::cfg().setopt<OptIntVec>("enrollments", {});
+        Face::cfg().set<std::int64_t>("challenge", 0);
+        Face::cfg().setopt<OptIntVec>("features", {});
+        Face::cfg().set<std::int64_t>("authenticator_id", 0);
+        Face::cfg().set<std::string>("strength", "");
+        Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {});
     }
 
     FakeFaceEngine mEngine;
@@ -160,81 +161,83 @@
 
 TEST_F(FakeFaceEngineTest, GenerateChallenge) {
     mEngine.generateChallengeImpl(mCallback.get());
-    ASSERT_EQ(FaceHalProperties::challenge().value(), mCallback->mLastChallenge);
+    ASSERT_EQ(Face::cfg().get<std::int64_t>("challenge"), mCallback->mLastChallenge);
 }
 
 TEST_F(FakeFaceEngineTest, RevokeChallenge) {
-    auto challenge = FaceHalProperties::challenge().value_or(10);
+    auto challenge = Face::cfg().get<std::int64_t>("challenge");
     mEngine.revokeChallengeImpl(mCallback.get(), challenge);
-    ASSERT_FALSE(FaceHalProperties::challenge().has_value());
+    ASSERT_FALSE(Face::cfg().get<std::int64_t>("challenge"));
     ASSERT_EQ(challenge, mCallback->mLastChallengeRevoked);
 }
 
 TEST_F(FakeFaceEngineTest, ResetLockout) {
-    FaceHalProperties::lockout(true);
+    Face::cfg().set<bool>("lockout", true);
     mEngine.resetLockoutImpl(mCallback.get(), {});
     ASSERT_FALSE(mCallback->mLockoutPermanent);
-    ASSERT_FALSE(FaceHalProperties::lockout().value_or(true));
+    ASSERT_FALSE(Face::cfg().get<bool>("lockout"));
 }
 
 TEST_F(FakeFaceEngineTest, AuthenticatorId) {
-    FaceHalProperties::authenticator_id(50);
+    Face::cfg().set<std::int64_t>("authenticator_id", 50);
     mEngine.getAuthenticatorIdImpl(mCallback.get());
     ASSERT_EQ(50, mCallback->mLastAuthenticatorId);
     ASSERT_FALSE(mCallback->mAuthenticatorIdInvalidated);
 }
 
 TEST_F(FakeFaceEngineTest, GetAuthenticatorIdWeakReturnsZero) {
-    FaceHalProperties::strength("weak");
-    FaceHalProperties::authenticator_id(500);
+    Face::cfg().set<std::string>("strength", "weak");
+    Face::cfg().set<std::int64_t>("authenticator_id", 500);
     mEngine.getAuthenticatorIdImpl(mCallback.get());
     ASSERT_EQ(0, mCallback->mLastAuthenticatorId);
     ASSERT_FALSE(mCallback->mAuthenticatorIdInvalidated);
 }
 
 TEST_F(FakeFaceEngineTest, AuthenticatorIdInvalidate) {
-    FaceHalProperties::authenticator_id(500);
+    Face::cfg().set<std::int64_t>("authenticator_id", 500);
     mEngine.invalidateAuthenticatorIdImpl(mCallback.get());
-    ASSERT_NE(500, FaceHalProperties::authenticator_id().value());
+    ASSERT_NE(500, Face::cfg().get<std::int64_t>("authenticator_id"));
     ASSERT_TRUE(mCallback->mAuthenticatorIdInvalidated);
 }
 
 TEST_F(FakeFaceEngineTest, Enroll) {
-    FaceHalProperties::next_enrollment("1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:true");
+    Face::cfg().set<std::string>("next_enrollment",
+                                 "1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:true");
     keymaster::HardwareAuthToken hat{.mac = {2, 4}};
     mEngine.enrollImpl(mCallback.get(), hat, {} /*enrollmentType*/, {} /*features*/,
                        mCancel.get_future());
-    ASSERT_FALSE(FaceHalProperties::next_enrollment().has_value());
-    ASSERT_EQ(1, FaceHalProperties::enrollments().size());
-    ASSERT_EQ(1, FaceHalProperties::enrollments()[0].value());
+    ASSERT_FALSE(Face::cfg().getopt<OptString>("next_enrollment").has_value());
+    ASSERT_EQ(1, Face::cfg().getopt<OptIntVec>("enrollments").size());
+    ASSERT_EQ(1, Face::cfg().getopt<OptIntVec>("enrollments")[0].value());
     ASSERT_EQ(1, mCallback->mLastEnrolled);
     ASSERT_EQ(0, mCallback->mRemaining);
 }
 
 TEST_F(FakeFaceEngineTest, EnrollFails) {
-    FaceHalProperties::next_enrollment("1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:false");
+    Face::cfg().set<std::string>("next_enrollment",
+                                 "1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:false");
     keymaster::HardwareAuthToken hat{.mac = {2, 4}};
     mEngine.enrollImpl(mCallback.get(), hat, {} /*enrollmentType*/, {} /*features*/,
                        mCancel.get_future());
-    ASSERT_FALSE(FaceHalProperties::next_enrollment().has_value());
-    ASSERT_EQ(0, FaceHalProperties::enrollments().size());
+    ASSERT_FALSE(Face::cfg().getopt<OptString>("next_enrollment").has_value());
+    ASSERT_EQ(0, Face::cfg().getopt<OptIntVec>("enrollments").size());
 }
 
 TEST_F(FakeFaceEngineTest, EnrollCancel) {
-    FaceHalProperties::next_enrollment("1:2000-[21,8,9],300:false");
+    Face::cfg().set<std::string>("next_enrollment", "1:2000-[21,8,9],300:false");
     keymaster::HardwareAuthToken hat{.mac = {2, 4}};
     mCancel.set_value();
     mEngine.enrollImpl(mCallback.get(), hat, {} /*enrollmentType*/, {} /*features*/,
                        mCancel.get_future());
     ASSERT_EQ(Error::CANCELED, mCallback->mError);
     ASSERT_EQ(-1, mCallback->mLastEnrolled);
-    ASSERT_EQ(0, FaceHalProperties::enrollments().size());
-    ASSERT_TRUE(FaceHalProperties::next_enrollment().has_value());
+    ASSERT_EQ(0, Face::cfg().getopt<OptIntVec>("enrollments").size());
+    ASSERT_FALSE(Face::cfg().get<std::string>("next_enrollment").empty());
 }
 
 TEST_F(FakeFaceEngineTest, Authenticate) {
-    FaceHalProperties::enrollments({100});
-    FaceHalProperties::enrollment_hit(100);
+    Face::cfg().setopt<OptIntVec>("enrollments", {100});
+    Face::cfg().set<std::int32_t>("enrollment_hit", 100);
     mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
 
     ASSERT_EQ(100, mCallback->mLastAuthenticated);
@@ -242,32 +245,32 @@
 }
 
 TEST_F(FakeFaceEngineTest, AuthenticateCancel) {
-    FaceHalProperties::enrollments({100});
-    FaceHalProperties::enrollment_hit(100);
+    Face::cfg().setopt<OptIntVec>("enrollments", {100});
+    Face::cfg().set<std::int32_t>("enrollment_hit", 100);
     mCancel.set_value();
     mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
     ASSERT_EQ(Error::CANCELED, mCallback->mError);
 }
 
 TEST_F(FakeFaceEngineTest, AuthenticateFailedForUnEnrolled) {
-    FaceHalProperties::enrollments({3});
-    FaceHalProperties::enrollment_hit(100);
+    Face::cfg().setopt<OptIntVec>("enrollments", {3});
+    Face::cfg().set<std::int32_t>("enrollment_hit", 100);
     mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
     ASSERT_EQ(Error::TIMEOUT, mCallback->mError);
     ASSERT_TRUE(mCallback->mAuthenticateFailed);
 }
 
 TEST_F(FakeFaceEngineTest, DetectInteraction) {
-    FaceHalProperties::enrollments({100});
-    FaceHalProperties::enrollment_hit(100);
+    Face::cfg().setopt<OptIntVec>("enrollments", {100});
+    Face::cfg().set<std::int32_t>("enrollment_hit", 100);
     ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
     mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
     ASSERT_EQ(1, mCallback->mInteractionDetectedCount);
 }
 
 TEST_F(FakeFaceEngineTest, DetectInteractionCancel) {
-    FaceHalProperties::enrollments({100});
-    FaceHalProperties::enrollment_hit(100);
+    Face::cfg().setopt<OptIntVec>("enrollments", {100});
+    Face::cfg().set<std::int32_t>("enrollment_hit", 100);
     mCancel.set_value();
     mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
     ASSERT_EQ(Error::CANCELED, mCallback->mError);
@@ -279,7 +282,7 @@
 }
 
 TEST_F(FakeFaceEngineTest, SetFeature) {
-    FaceHalProperties::enrollments({1});
+    Face::cfg().setopt<OptIntVec>("enrollments", {1});
     keymaster::HardwareAuthToken hat{.mac = {2, 4}};
     mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
     auto features = mCallback->mFeatures;
@@ -294,7 +297,7 @@
 }
 
 TEST_F(FakeFaceEngineTest, ToggleFeature) {
-    FaceHalProperties::enrollments({1});
+    Face::cfg().setopt<OptIntVec>("enrollments", {1});
     keymaster::HardwareAuthToken hat{.mac = {2, 4}};
     mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
     mEngine.getFeaturesImpl(mCallback.get());
@@ -310,7 +313,7 @@
 }
 
 TEST_F(FakeFaceEngineTest, TurningOffNonExistentFeatureDoesNothing) {
-    FaceHalProperties::enrollments({1});
+    Face::cfg().setopt<OptIntVec>("enrollments", {1});
     keymaster::HardwareAuthToken hat{.mac = {2, 4}};
     mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, false);
     mEngine.getFeaturesImpl(mCallback.get());
@@ -319,7 +322,7 @@
 }
 
 TEST_F(FakeFaceEngineTest, SetMultipleFeatures) {
-    FaceHalProperties::enrollments({1});
+    Face::cfg().setopt<OptIntVec>("enrollments", {1});
     keymaster::HardwareAuthToken hat{.mac = {2, 4}};
     mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
     mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_DIVERSE_POSES, true);
@@ -335,7 +338,7 @@
 }
 
 TEST_F(FakeFaceEngineTest, SetMultipleFeaturesAndTurnOffSome) {
-    FaceHalProperties::enrollments({1});
+    Face::cfg().setopt<OptIntVec>("enrollments", {1});
     keymaster::HardwareAuthToken hat{.mac = {2, 4}};
     mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
     mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_DIVERSE_POSES, true);
@@ -352,7 +355,7 @@
 }
 
 TEST_F(FakeFaceEngineTest, Enumerate) {
-    FaceHalProperties::enrollments({120, 3});
+    Face::cfg().setopt<OptIntVec>("enrollments", {120, 3});
     mEngine.enumerateEnrollmentsImpl(mCallback.get());
     auto enrolls = mCallback->mLastEnrollmentsEnumerated;
     ASSERT_FALSE(enrolls.empty());
@@ -361,7 +364,7 @@
 }
 
 TEST_F(FakeFaceEngineTest, RemoveEnrollments) {
-    FaceHalProperties::enrollments({120, 3, 100});
+    Face::cfg().setopt<OptIntVec>("enrollments", {120, 3, 100});
     mEngine.removeEnrollmentsImpl(mCallback.get(), {120, 100});
     mEngine.enumerateEnrollmentsImpl(mCallback.get());
     auto enrolls = mCallback->mLastEnrollmentsEnumerated;
@@ -372,9 +375,9 @@
 }
 
 TEST_F(FakeFaceEngineTest, ResetLockoutWithAuth) {
-    FaceHalProperties::lockout(true);
-    FaceHalProperties::enrollments({33});
-    FaceHalProperties::enrollment_hit(33);
+    Face::cfg().set<bool>("lockout", true);
+    Face::cfg().setopt<OptIntVec>("enrollments", {33});
+    Face::cfg().set<std::int32_t>("enrollment_hit", 33);
     auto cancelFuture = mCancel.get_future();
     mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, cancelFuture);
 
@@ -382,28 +385,30 @@
 
     mEngine.resetLockoutImpl(mCallback.get(), {} /* hat */);
     ASSERT_FALSE(mCallback->mLockoutPermanent);
-    FaceHalProperties::enrollment_hit(33);
+    Face::cfg().set<std::int32_t>("enrollment_hit", 33);
     mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, cancelFuture);
     ASSERT_EQ(33, mCallback->mLastAuthenticated);
     ASSERT_FALSE(mCallback->mAuthenticateFailed);
 }
 
 TEST_F(FakeFaceEngineTest, LatencyDefault) {
-    FaceHalProperties::operation_detect_interaction_latency({});
-    ASSERT_EQ(DEFAULT_LATENCY,
-              mEngine.getLatency(FaceHalProperties::operation_detect_interaction_latency()));
+    Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {});
+    ASSERT_EQ(DEFAULT_LATENCY, mEngine.getLatency(Face::cfg().getopt<OptIntVec>(
+                                       "operation_detect_interaction_latency")));
 }
 
 TEST_F(FakeFaceEngineTest, LatencyFixed) {
-    FaceHalProperties::operation_detect_interaction_latency({10});
-    ASSERT_EQ(10, mEngine.getLatency(FaceHalProperties::operation_detect_interaction_latency()));
+    Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {10});
+    ASSERT_EQ(10, mEngine.getLatency(
+                          Face::cfg().getopt<OptIntVec>("operation_detect_interaction_latency")));
 }
 
 TEST_F(FakeFaceEngineTest, LatencyRandom) {
-    FaceHalProperties::operation_detect_interaction_latency({1, 1000});
+    Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {1, 1000});
     std::set<int32_t> latencySet;
     for (int i = 0; i < 100; i++) {
-        auto x = mEngine.getLatency(FaceHalProperties::operation_detect_interaction_latency());
+        auto x = mEngine.getLatency(
+                Face::cfg().getopt<OptIntVec>("operation_detect_interaction_latency"));
         ASSERT_TRUE(x >= 1 && x <= 1000);
         latencySet.insert(x);
     }
diff --git a/biometrics/face/aidl/default/tests/FakeLockoutTrackerTest.cpp b/biometrics/face/aidl/default/tests/FakeLockoutTrackerTest.cpp
index fa07d1d..8564f6b 100644
--- a/biometrics/face/aidl/default/tests/FakeLockoutTrackerTest.cpp
+++ b/biometrics/face/aidl/default/tests/FakeLockoutTrackerTest.cpp
@@ -21,6 +21,7 @@
 
 #include <android-base/logging.h>
 
+#include "Face.h"
 #include "FakeLockoutTracker.h"
 #include "util/Util.h"
 
@@ -103,19 +104,21 @@
     static constexpr int32_t LOCKOUT_TIMED_DURATION = 100;
 
     void SetUp() override {
-        FaceHalProperties::lockout_timed_threshold(LOCKOUT_TIMED_THRESHOLD);
-        FaceHalProperties::lockout_timed_duration(LOCKOUT_TIMED_DURATION);
-        FaceHalProperties::lockout_permanent_threshold(LOCKOUT_PERMANENT_THRESHOLD);
+        Face::cfg().set<std::int32_t>("lockout_timed_threshold", LOCKOUT_TIMED_THRESHOLD);
+        Face::cfg().set<std::int32_t>("lockout_timed_duration", LOCKOUT_TIMED_DURATION);
+        Face::cfg().set<std::int32_t>("lockout_permanent_threshold", LOCKOUT_PERMANENT_THRESHOLD);
+        Face::cfg().set<bool>("lockout_enable", false);
+        Face::cfg().set<bool>("lockout", false);
         mCallback = ndk::SharedRefBase::make<TestSessionCallback>();
     }
 
     void TearDown() override {
         // reset to default
-        FaceHalProperties::lockout_timed_threshold(5);
-        FaceHalProperties::lockout_timed_duration(20);
-        FaceHalProperties::lockout_permanent_threshold(10000);
-        FaceHalProperties::lockout_enable(false);
-        FaceHalProperties::lockout(false);
+        Face::cfg().set<std::int32_t>("lockout_timed_threshold", 5);
+        Face::cfg().set<std::int32_t>("lockout_timed_duration", 20);
+        Face::cfg().set<std::int32_t>("lockout_permanent_threshold", 10000);
+        Face::cfg().set<bool>("lockout_enable", false);
+        Face::cfg().set<bool>("lockout", false);
     }
 
     FakeLockoutTracker mLockoutTracker;
@@ -123,7 +126,7 @@
 };
 
 TEST_F(FakeLockoutTrackerTest, addFailedAttemptDisable) {
-    FaceHalProperties::lockout_enable(false);
+    Face::cfg().set<bool>("lockout_enable", false);
     for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD + 1; i++)
         mLockoutTracker.addFailedAttempt(mCallback.get());
     ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
@@ -131,7 +134,7 @@
 }
 
 TEST_F(FakeLockoutTrackerTest, addFailedAttemptPermanent) {
-    FaceHalProperties::lockout_enable(true);
+    Face::cfg().set<bool>("lockout_enable", true);
     ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
     for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD - 1; i++)
         mLockoutTracker.addFailedAttempt(mCallback.get());
@@ -145,8 +148,8 @@
 }
 
 TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimed) {
-    FaceHalProperties::lockout_enable(true);
-    FaceHalProperties::lockout_timed_enable(true);
+    Face::cfg().set<bool>("lockout_enable", true);
+    Face::cfg().set<bool>("lockout_timed_enable", true);
     ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
     for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++)
         mLockoutTracker.addFailedAttempt(mCallback.get());
@@ -168,8 +171,8 @@
 }
 
 TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockout_TimedThenPermanent) {
-    FaceHalProperties::lockout_enable(true);
-    FaceHalProperties::lockout_timed_enable(true);
+    Face::cfg().set<bool>("lockout_enable", true);
+    Face::cfg().set<bool>("lockout_timed_enable", true);
     ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
     for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++)
         mLockoutTracker.addFailedAttempt(mCallback.get());
@@ -182,8 +185,8 @@
 }
 
 TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimedTwice) {
-    FaceHalProperties::lockout_enable(true);
-    FaceHalProperties::lockout_timed_enable(true);
+    Face::cfg().set<bool>("lockout_enable", true);
+    Face::cfg().set<bool>("lockout_timed_enable", true);
     ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
     ASSERT_EQ(0, mCallback->mLockoutTimed);
     for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++)
@@ -198,7 +201,7 @@
 }
 
 TEST_F(FakeLockoutTrackerTest, resetLockout) {
-    FaceHalProperties::lockout_enable(true);
+    Face::cfg().set<bool>("lockout_enable", true);
     ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
     for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD; i++)
         mLockoutTracker.addFailedAttempt(mCallback.get());
diff --git a/biometrics/face/aidl/default/tests/VirtualHalTest.cpp b/biometrics/face/aidl/default/tests/VirtualHalTest.cpp
new file mode 100644
index 0000000..2f19805
--- /dev/null
+++ b/biometrics/face/aidl/default/tests/VirtualHalTest.cpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2024 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 <android/binder_process.h>
+#include <face.sysprop.h>
+#include <gtest/gtest.h>
+
+#include <android-base/logging.h>
+
+#include "Face.h"
+#include "VirtualHal.h"
+
+using namespace ::android::face::virt;
+using namespace ::aidl::android::hardware::biometrics::face;
+
+namespace aidl::android::hardware::biometrics::face {
+
+class VirtualHalTest : public ::testing::Test {
+  public:
+    static const int32_t STATUS_FAILED_TO_SET_PARAMETER = 2;
+
+  protected:
+    void SetUp() override {
+        mHal = ndk::SharedRefBase::make<Face>();
+        mVhal = ndk::SharedRefBase::make<VirtualHal>(mHal);
+        ASSERT_TRUE(mVhal != nullptr);
+        mHal->resetConfigToDefault();
+    }
+
+    void TearDown() override { mHal->resetConfigToDefault(); }
+
+    std::shared_ptr<VirtualHal> mVhal;
+
+    ndk::ScopedAStatus validateNonNegativeInputOfInt32(const char* name,
+                                                       ndk::ScopedAStatus (VirtualHal::*f)(int32_t),
+                                                       const std::vector<int32_t>& in_good);
+
+  private:
+    std::shared_ptr<Face> mHal;
+};
+
+ndk::ScopedAStatus VirtualHalTest::validateNonNegativeInputOfInt32(
+        const char* name, ndk::ScopedAStatus (VirtualHal::*f)(int32_t),
+        const std::vector<int32_t>& in_params_good) {
+    ndk::ScopedAStatus status;
+    for (auto& param : in_params_good) {
+        status = (*mVhal.*f)(param);
+        if (!status.isOk()) return status;
+        if (Face::cfg().get<int32_t>(name) != param) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER,
+                    "Error: fail to set non-negative parameter"));
+        }
+    }
+
+    int32_t old_param = Face::cfg().get<int32_t>(name);
+    status = (*mVhal.*f)(-1);
+    if (status.isOk()) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER, "Error: should return NOK"));
+    }
+    if (status.getServiceSpecificError() != IVirtualHal::STATUS_INVALID_PARAMETER) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER,
+                "Error: unexpected return error code"));
+    }
+    if (Face::cfg().get<int32_t>(name) != old_param) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER,
+                "Error: unexpected parameter change on failed attempt"));
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+TEST_F(VirtualHalTest, init) {
+    mVhal->setLockout(false);
+    ASSERT_TRUE(Face::cfg().get<bool>("lockout") == false);
+    ASSERT_TRUE(Face::cfg().get<std::string>("type") == "rgb");
+    ASSERT_TRUE(Face::cfg().get<std::string>("strength") == "strong");
+    std::int64_t id = Face::cfg().get<std::int64_t>("authenticator_id");
+    ASSERT_TRUE(Face::cfg().get<std::int64_t>("authenticator_id") == 0);
+    ASSERT_TRUE(Face::cfg().getopt<OptIntVec>("enrollments") == OptIntVec());
+}
+
+TEST_F(VirtualHalTest, enrollment_hit_int32) {
+    mVhal->setEnrollmentHit(11);
+    ASSERT_TRUE(Face::cfg().get<int32_t>("enrollment_hit") == 11);
+}
+
+TEST_F(VirtualHalTest, next_enrollment) {
+    struct {
+        std::string nextEnrollmentStr;
+        face::NextEnrollment nextEnrollment;
+    } testData[] = {
+            {"1:20:true", {1, {{20}}, true}},
+            {"1:50,60,70:true", {1, {{50}, {60}, {70}}, true}},
+            {"2:50-[21],60,70-[4,1002,1]:false",
+             {2,
+              {{50, {{AcquiredInfo::START}}},
+               {60},
+               {70, {{AcquiredInfo::TOO_DARK}, {1002}, {AcquiredInfo::GOOD}}}},
+              false}},
+    };
+
+    for (auto& d : testData) {
+        mVhal->setNextEnrollment(d.nextEnrollment);
+        ASSERT_TRUE(Face::cfg().get<std::string>("next_enrollment") == d.nextEnrollmentStr);
+    }
+}
+
+TEST_F(VirtualHalTest, authenticator_id_int64) {
+    mVhal->setAuthenticatorId(12345678900);
+    ASSERT_TRUE(Face::cfg().get<int64_t>("authenticator_id") == 12345678900);
+}
+
+TEST_F(VirtualHalTest, opeationAuthenticateFails_bool) {
+    mVhal->setOperationAuthenticateFails(true);
+    ASSERT_TRUE(Face::cfg().get<bool>("operation_authenticate_fails"));
+}
+
+TEST_F(VirtualHalTest, operationAuthenticateAcquired_int32_vector) {
+    using Tag = AcquiredInfoAndVendorCode::Tag;
+    std::vector<AcquiredInfoAndVendorCode> ac{
+            {AcquiredInfo::START}, {AcquiredInfo::TOO_FAR}, {1023}};
+    mVhal->setOperationAuthenticateAcquired(ac);
+    OptIntVec ac_get = Face::cfg().getopt<OptIntVec>("operation_authenticate_acquired");
+    ASSERT_TRUE(ac_get.size() == ac.size());
+    for (int i = 0; i < ac.size(); i++) {
+        int acCode = (ac[i].getTag() == Tag::acquiredInfo) ? (int)ac[i].get<Tag::acquiredInfo>()
+                                                           : ac[i].get<Tag::vendorCode>();
+        ASSERT_TRUE(acCode == ac_get[i]);
+    }
+}
+
+TEST_F(VirtualHalTest, type) {
+    struct {
+        FaceSensorType type;
+        const char* typeStr;
+    } typeMap[] = {{FaceSensorType::RGB, "rgb"},
+                   {FaceSensorType::IR, "ir"},
+                   {FaceSensorType::UNKNOWN, "unknown"}};
+    for (auto const& x : typeMap) {
+        mVhal->setType(x.type);
+        ASSERT_TRUE(Face::cfg().get<std::string>("type") == x.typeStr);
+    }
+}
+
+TEST_F(VirtualHalTest, sensorStrength) {
+    struct {
+        common::SensorStrength strength;
+        const char* strengthStr;
+    } strengths[] = {{common::SensorStrength::CONVENIENCE, "CONVENIENCE"},
+                     {common::SensorStrength::WEAK, "WEAK"},
+                     {common::SensorStrength::STRONG, "STRONG"}};
+
+    for (auto const& x : strengths) {
+        mVhal->setSensorStrength(x.strength);
+        ASSERT_TRUE(Face::cfg().get<std::string>("strength") == x.strengthStr);
+    }
+}
+
+TEST_F(VirtualHalTest, setLatency) {
+    ndk::ScopedAStatus status;
+    std::vector<int32_t> in_lats[] = {{1}, {2, 3}, {5, 4}};
+    for (auto const& in_lat : in_lats) {
+        status = mVhal->setOperationAuthenticateLatency(in_lat);
+        ASSERT_TRUE(status.isOk());
+        OptIntVec out_lat = Face::cfg().getopt<OptIntVec>("operation_authenticate_latency");
+        ASSERT_TRUE(in_lat.size() == out_lat.size());
+        for (int i = 0; i < in_lat.size(); i++) {
+            ASSERT_TRUE(in_lat[i] == out_lat[i]);
+        }
+    }
+
+    std::vector<int32_t> bad_in_lats[] = {{}, {1, 2, 3}, {1, -3}};
+    for (auto const& in_lat : bad_in_lats) {
+        status = mVhal->setOperationAuthenticateLatency(in_lat);
+        ASSERT_TRUE(!status.isOk());
+        ASSERT_TRUE(status.getServiceSpecificError() == IVirtualHal::STATUS_INVALID_PARAMETER);
+    }
+}
+
+TEST_F(VirtualHalTest, setOperationAuthenticateDuration) {
+    ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
+            "operation_authenticate_duration", &IVirtualHal::setOperationAuthenticateDuration,
+            {0, 33});
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(VirtualHalTest, setLockoutTimedDuration) {
+    ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
+            "lockout_timed_duration", &IVirtualHal::setLockoutTimedDuration, {0, 35});
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(VirtualHalTest, setLockoutTimedThreshold) {
+    ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
+            "lockout_timed_threshold", &IVirtualHal::setLockoutTimedThreshold, {0, 36});
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(VirtualHalTest, setLockoutPermanentThreshold) {
+    ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
+            "lockout_permanent_threshold", &IVirtualHal::setLockoutPermanentThreshold, {0, 37});
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(VirtualHalTest, setOthers) {
+    // Verify that there is no CHECK() failures
+    mVhal->setEnrollments({7, 6, 5});
+    mVhal->setChallenge(111222333444555666);
+    mVhal->setOperationAuthenticateError(4);
+    mVhal->setOperationEnrollLatency({4, 5});
+    mVhal->setLockout(false);
+    mVhal->setLockoutEnable(false);
+}
+
+}  // namespace aidl::android::hardware::biometrics::face
+
+int main(int argc, char** argv) {
+    testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/biometrics/fingerprint/2.1/vts/functional/Android.bp b/biometrics/fingerprint/2.1/vts/functional/Android.bp
index 68b3360..819feb4 100644
--- a/biometrics/fingerprint/2.1/vts/functional/Android.bp
+++ b/biometrics/fingerprint/2.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_biometrics_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/biometrics/fingerprint/2.2/vts/functional/Android.bp b/biometrics/fingerprint/2.2/vts/functional/Android.bp
index 02f833a..11315fa 100644
--- a/biometrics/fingerprint/2.2/vts/functional/Android.bp
+++ b/biometrics/fingerprint/2.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
  */
 
 package {
+    default_team: "trendy_team_biometrics_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/biometrics/fingerprint/aidl/Android.bp b/biometrics/fingerprint/aidl/Android.bp
index a395c01..9f9e723 100644
--- a/biometrics/fingerprint/aidl/Android.bp
+++ b/biometrics/fingerprint/aidl/Android.bp
@@ -11,7 +11,7 @@
     name: "android.hardware.biometrics.fingerprint",
     vendor_available: true,
     srcs: [
-        "android/hardware/biometrics/fingerprint/**/*.aidl",
+        "android/hardware/biometrics/fingerprint/*.aidl",
     ],
     imports: [
         "android.hardware.biometrics.common-V4",
@@ -25,6 +25,15 @@
         cpp: {
             enabled: false,
         },
+        ndk: {
+            apex_available: [
+                "//apex_available:platform",
+                "//apex_available:anyapex",
+            ],
+        },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
@@ -57,5 +66,34 @@
         },
 
     ],
+    frozen: true,
+}
+
+aidl_interface {
+    name: "android.hardware.biometrics.fingerprint.virtualhal",
+    srcs: [
+        "android/hardware/biometrics/fingerprint/virtualhal/*.aidl",
+    ],
+    imports: [
+        "android.hardware.biometrics.common-V4",
+        "android.hardware.keymaster-V4",
+        "android.hardware.biometrics.fingerprint-V4",
+    ],
+    vendor_available: true,
+    unstable: true,
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        cpp: {
+            enabled: false,
+        },
+        ndk: {
+            apex_available: [
+                "com.android.hardware.biometrics.fingerprint.virtual",
+                "//apex_available:platform",
+            ],
+        },
+    },
     frozen: false,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IVirtualHal.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
deleted file mode 100644
index 33ae83c..0000000
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.biometrics.fingerprint;
-/* @hide */
-@VintfStability
-interface IVirtualHal {
-  oneway void setEnrollments(in int[] id);
-  oneway void setEnrollmentHit(in int hit_id);
-  oneway void setNextEnrollment(in android.hardware.biometrics.fingerprint.NextEnrollment next_enrollment);
-  oneway void setAuthenticatorId(in long id);
-  oneway void setChallenge(in long challenge);
-  oneway void setOperationAuthenticateFails(in boolean fail);
-  oneway void setOperationAuthenticateLatency(in int[] latencyMs);
-  oneway void setOperationAuthenticateDuration(in int durationMs);
-  oneway void setOperationAuthenticateError(in int error);
-  oneway void setOperationAuthenticateAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquired);
-  oneway void setOperationEnrollError(in int error);
-  oneway void setOperationEnrollLatency(in int[] latencyMs);
-  oneway void setOperationDetectInteractionLatency(in int[] latencyMs);
-  oneway void setOperationDetectInteractionError(in int error);
-  oneway void setOperationDetectInteractionDuration(in int durationMs);
-  oneway void setOperationDetectInteractionAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquired);
-  oneway void setLockout(in boolean lockout);
-  oneway void setLockoutEnable(in boolean enable);
-  oneway void setLockoutTimedThreshold(in int threshold);
-  oneway void setLockoutTimedDuration(in int durationMs);
-  oneway void setLockoutPermanentThreshold(in int threshold);
-  oneway void resetConfigurations();
-  oneway void setType(in android.hardware.biometrics.fingerprint.FingerprintSensorType type);
-  oneway void setSensorId(in int id);
-  oneway void setSensorStrength(in android.hardware.biometrics.common.SensorStrength strength);
-  oneway void setMaxEnrollmentPerUser(in int max);
-  oneway void setSensorLocation(in android.hardware.biometrics.fingerprint.SensorLocation loc);
-  oneway void setNavigationGuesture(in boolean v);
-  oneway void setDetectInteraction(in boolean v);
-  oneway void setDisplayTouch(in boolean v);
-  oneway void setControlIllumination(in boolean v);
-  const int STATUS_INVALID_PARAMETER = 1;
-}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/AcquiredInfoAndVendorCode.aidl
similarity index 93%
rename from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
rename to biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/AcquiredInfoAndVendorCode.aidl
index c7be950..1fc7221 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/AcquiredInfoAndVendorCode.aidl
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.biometrics.fingerprint.virtualhal;
 
 import android.hardware.biometrics.fingerprint.AcquiredInfo;
 
 /**
  * @hide
  */
-@VintfStability
 union AcquiredInfoAndVendorCode {
     /**
      * Acquired info as specified in AcqauiredInfo.aidl
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/EnrollmentProgressStep.aidl
similarity index 87%
rename from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
rename to biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/EnrollmentProgressStep.aidl
index bf038f6..b0b2926 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/EnrollmentProgressStep.aidl
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.biometrics.fingerprint.virtualhal;
 
-import android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode;
+import android.hardware.biometrics.fingerprint.virtualhal.AcquiredInfoAndVendorCode;
 
 /**
  * @hide
  */
-@VintfStability
 parcelable EnrollmentProgressStep {
     /**
      * The duration of the enrollment step in milli-seconds
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/IVirtualHal.aidl
similarity index 96%
rename from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
rename to biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/IVirtualHal.aidl
index cb9135e..5af84ed 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/IVirtualHal.aidl
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.biometrics.fingerprint.virtualhal;
 
 import android.hardware.biometrics.common.SensorStrength;
-import android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode;
 import android.hardware.biometrics.fingerprint.FingerprintSensorType;
-import android.hardware.biometrics.fingerprint.NextEnrollment;
+import android.hardware.biometrics.fingerprint.IFingerprint;
 import android.hardware.biometrics.fingerprint.SensorLocation;
+import android.hardware.biometrics.fingerprint.virtualhal.AcquiredInfoAndVendorCode;
+import android.hardware.biometrics.fingerprint.virtualhal.NextEnrollment;
 
 /**
  * @hide
  */
-@VintfStability
-oneway interface IVirtualHal {
+interface IVirtualHal {
     /**
      * The operation failed due to invalid input parameters, the error messages should
      * gives more details
@@ -315,4 +315,5 @@
     void setDetectInteraction(in boolean v);
     void setDisplayTouch(in boolean v);
     void setControlIllumination(in boolean v);
+    IFingerprint getFingerprintHal();
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/NextEnrollment.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/NextEnrollment.aidl
similarity index 85%
copy from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
copy to biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/NextEnrollment.aidl
index 4b50850..2d704f1 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/NextEnrollment.aidl
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.biometrics.fingerprint.virtualhal;
+
+import android.hardware.biometrics.fingerprint.virtualhal.EnrollmentProgressStep;
 
 /**
  * @hide
  */
-@VintfStability
 parcelable NextEnrollment {
     /**
      *  Identifier of the next enrollment if successful
@@ -31,7 +32,7 @@
      *  and sequence of acquired info codes to be generated by HAL.
      *  See EnrollmentProgressStep.aidl for more details
      */
-    android.hardware.biometrics.fingerprint.EnrollmentProgressStep[] progressSteps;
+    EnrollmentProgressStep[] progressSteps;
 
     /**
      * Success or failure of the next enrollment
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/README.md b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/README.md
new file mode 100644
index 0000000..eaf2336
--- /dev/null
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/virtualhal/README.md
@@ -0,0 +1,2 @@
+The aidl files in this directory are used only by fingerprint virtual hal
+which is controlled/configured via IVirtualHal interface
diff --git a/biometrics/fingerprint/aidl/default/Android.bp b/biometrics/fingerprint/aidl/default/Android.bp
index 9b72c87..c6ffc51 100644
--- a/biometrics/fingerprint/aidl/default/Android.bp
+++ b/biometrics/fingerprint/aidl/default/Android.bp
@@ -8,10 +8,9 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-cc_binary {
-    name: "android.hardware.biometrics.fingerprint-service.example",
-    vendor: true,
-    relative_install_path: "hw",
+cc_library_static {
+    name: "android.hardware.biometrics.fingerprint-service.lib",
+    vendor_available: true,
     local_include_dirs: ["include"],
     srcs: [
         "FakeLockoutTracker.cpp",
@@ -30,22 +29,86 @@
         "libbinder_ndk",
         "liblog",
     ],
-    static_libs: [
+    whole_static_libs: [
         "libandroid.hardware.biometrics.fingerprint.VirtualProps",
         "libbase",
-        "android.hardware.biometrics.fingerprint-V5-ndk",
+        "android.hardware.biometrics.fingerprint.virtualhal-ndk",
+        "android.hardware.biometrics.fingerprint-V4-ndk",
         "android.hardware.biometrics.common-V4-ndk",
         "android.hardware.biometrics.common.thread",
         "android.hardware.biometrics.common.util",
         "android.hardware.biometrics.common.config",
         "android.hardware.keymaster-V4-ndk",
     ],
+    product_variables: {
+        debuggable: {
+            cflags: ["-DFPS_DEBUGGABLE"],
+        },
+    },
+    apex_available: [
+        "com.android.hardware.biometrics.fingerprint.virtual",
+        "//apex_available:platform",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.biometrics.fingerprint-service.example",
+    system_ext_specific: true,
+    relative_install_path: "hw",
+    local_include_dirs: ["include"],
+    srcs: [
+    ],
+    stl: "c++_static",
+    shared_libs: [
+        "libbinder_ndk",
+        "liblog",
+    ],
+    whole_static_libs: [
+        "android.hardware.biometrics.fingerprint-service.lib",
+    ],
     installable: false, // install APEX instead
     product_variables: {
         debuggable: {
             cflags: ["-DFPS_DEBUGGABLE"],
         },
     },
+    apex_available: [
+        "com.android.hardware.biometrics.fingerprint.virtual",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.biometrics.fingerprint-service.default",
+    //system_ext_specific: true,
+    vendor: true,
+    relative_install_path: "hw",
+    init_rc: ["fingerprint-default.rc"],
+    vintf_fragment_modules: ["android.hardware.biometrics.fingerprint-service.default.vintf"],
+    local_include_dirs: ["include"],
+    srcs: [
+    ],
+    stl: "c++_static",
+    shared_libs: [
+        "libbinder_ndk",
+        "liblog",
+    ],
+    whole_static_libs: [
+        "android.hardware.biometrics.fingerprint-service.lib",
+    ],
+    product_variables: {
+        debuggable: {
+            cflags: ["-DFPS_DEBUGGABLE"],
+        },
+    },
+    apex_available: [
+        "//apex_available:platform",
+    ],
+}
+
+vintf_fragment {
+    name: "android.hardware.biometrics.fingerprint-service.default.vintf",
+    src: "fingerprint-default.xml",
+    vendor: true,
 }
 
 cc_test {
@@ -63,14 +126,13 @@
     ],
     static_libs: [
         "libandroid.hardware.biometrics.fingerprint.VirtualProps",
-        "android.hardware.biometrics.fingerprint-V5-ndk",
+        "android.hardware.biometrics.fingerprint-V4-ndk",
         "android.hardware.biometrics.common-V4-ndk",
         "android.hardware.keymaster-V4-ndk",
         "android.hardware.biometrics.common.util",
         "android.hardware.biometrics.common.config",
         "android.hardware.biometrics.common.thread",
     ],
-    vendor: true,
     test_suites: ["general-tests"],
     require_root: true,
 }
@@ -91,14 +153,13 @@
     ],
     static_libs: [
         "libandroid.hardware.biometrics.fingerprint.VirtualProps",
-        "android.hardware.biometrics.fingerprint-V5-ndk",
+        "android.hardware.biometrics.fingerprint-V4-ndk",
         "android.hardware.biometrics.common-V4-ndk",
         "android.hardware.keymaster-V4-ndk",
         "android.hardware.biometrics.common.util",
         "android.hardware.biometrics.common.config",
         "android.hardware.biometrics.common.thread",
     ],
-    vendor: true,
     test_suites: ["general-tests"],
     require_root: true,
 }
@@ -117,14 +178,13 @@
     ],
     static_libs: [
         "libandroid.hardware.biometrics.fingerprint.VirtualProps",
-        "android.hardware.biometrics.fingerprint-V5-ndk",
+        "android.hardware.biometrics.fingerprint-V4-ndk",
         "android.hardware.biometrics.common-V4-ndk",
         "android.hardware.keymaster-V4-ndk",
         "android.hardware.biometrics.common.util",
         "android.hardware.biometrics.common.thread",
         "android.hardware.biometrics.common.config",
     ],
-    vendor: true,
     test_suites: ["general-tests"],
     require_root: true,
 }
@@ -145,14 +205,13 @@
     ],
     static_libs: [
         "libandroid.hardware.biometrics.fingerprint.VirtualProps",
-        "android.hardware.biometrics.fingerprint-V5-ndk",
+        "android.hardware.biometrics.fingerprint-V4-ndk",
         "android.hardware.biometrics.common-V4-ndk",
         "android.hardware.keymaster-V4-ndk",
         "android.hardware.biometrics.common.util",
         "android.hardware.biometrics.common.thread",
         "android.hardware.biometrics.common.config",
     ],
-    vendor: true,
     test_suites: ["general-tests"],
     require_root: true,
 }
@@ -178,7 +237,8 @@
     ],
     static_libs: [
         "libandroid.hardware.biometrics.fingerprint.VirtualProps",
-        "android.hardware.biometrics.fingerprint-V5-ndk",
+        "android.hardware.biometrics.fingerprint-V4-ndk",
+        "android.hardware.biometrics.fingerprint.virtualhal-ndk",
         "android.hardware.biometrics.common-V4-ndk",
         "android.hardware.keymaster-V4-ndk",
         "android.hardware.biometrics.common.util",
@@ -190,7 +250,6 @@
             cflags: ["-DFPS_DEBUGGABLE"],
         },
     },
-    vendor: true,
     test_suites: ["general-tests"],
     require_root: true,
 }
@@ -198,39 +257,34 @@
 sysprop_library {
     name: "android.hardware.biometrics.fingerprint.VirtualProps",
     srcs: ["fingerprint.sysprop"],
-    property_owner: "Vendor",
-    vendor: true,
+    property_owner: "Platform",
+    vendor_available: true,
+    apex_available: [
+        "com.android.hardware.biometrics.fingerprint.virtual",
+        "//apex_available:platform",
+    ],
 }
 
 prebuilt_etc {
-    name: "fingerprint-example.rc",
-    src: "fingerprint-example.rc",
-    installable: false,
-}
-
-prebuilt_etc {
-    name: "fingerprint-example.xml",
-    src: "fingerprint-example.xml",
-    sub_dir: "vintf",
+    name: "fingerprint-virtual.rc",
+    src: "fingerprint-virtual.rc",
     installable: false,
 }
 
 apex {
     name: "com.android.hardware.biometrics.fingerprint.virtual",
     manifest: "apex_manifest.json",
-    file_contexts: "apex_file_contexts",
+    file_contexts: ":com.android.biometrics.virtual.fingerprint-file_contexts",
     key: "com.android.hardware.key",
     certificate: ":com.android.hardware.certificate",
     updatable: false,
-    vendor: true,
+    system_ext_specific: true,
 
     binaries: [
         "android.hardware.biometrics.fingerprint-service.example",
     ],
     prebuilts: [
         // init_rc
-        "fingerprint-example.rc",
-        // vintf_fragment
-        "fingerprint-example.xml",
+        "fingerprint-virtual.rc",
     ],
 }
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index 67eb837..7a43d7b 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -389,10 +389,10 @@
     if (isLockoutTimerStarted) isLockoutTimerAborted = true;
 }
 
-void FakeFingerprintEngine::clearLockout(ISessionCallback* cb) {
+void FakeFingerprintEngine::clearLockout(ISessionCallback* cb, bool dueToTimeout) {
     Fingerprint::cfg().set<bool>("lockout", false);
     cb->onLockoutCleared();
-    mLockoutTracker.reset();
+    mLockoutTracker.reset(dueToTimeout);
 }
 
 ndk::ScopedAStatus FakeFingerprintEngine::onPointerDownImpl(int32_t /*pointerId*/, int32_t /*x*/,
@@ -536,7 +536,7 @@
 void FakeFingerprintEngine::lockoutTimerExpired(ISessionCallback* cb) {
     BEGIN_OP(0);
     if (!isLockoutTimerAborted) {
-        clearLockout(cb);
+        clearLockout(cb, true);
     }
     isLockoutTimerStarted = false;
     isLockoutTimerAborted = false;
diff --git a/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp b/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
index a056db5..7d46845 100644
--- a/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
@@ -23,8 +23,11 @@
 
 namespace aidl::android::hardware::biometrics::fingerprint {
 
-void FakeLockoutTracker::reset() {
-    mFailedCount = 0;
+void FakeLockoutTracker::reset(bool dueToTimeout) {
+    if (!dueToTimeout) {
+        mFailedCount = 0;
+    }
+    mFailedCountTimed = 0;
     mLockoutTimedStart = 0;
     mCurrentMode = LockoutMode::kNone;
 }
@@ -33,6 +36,7 @@
     bool enabled = Fingerprint::cfg().get<bool>("lockout_enable");
     if (enabled) {
         mFailedCount++;
+        mFailedCountTimed++;
         int32_t lockoutTimedThreshold =
                 Fingerprint::cfg().get<std::int32_t>("lockout_timed_threshold");
         int32_t lockoutPermanetThreshold =
@@ -40,7 +44,7 @@
         if (mFailedCount >= lockoutPermanetThreshold) {
             mCurrentMode = LockoutMode::kPermanent;
             Fingerprint::cfg().set<bool>("lockout", true);
-        } else if (mFailedCount >= lockoutTimedThreshold) {
+        } else if (mFailedCountTimed >= lockoutTimedThreshold) {
             if (mCurrentMode == LockoutMode::kNone) {
                 mCurrentMode = LockoutMode::kTimed;
                 mLockoutTimedStart = Util::getSystemNanoTime();
diff --git a/biometrics/fingerprint/aidl/default/VirtualHal.cpp b/biometrics/fingerprint/aidl/default/VirtualHal.cpp
index e107d2f..d161765 100644
--- a/biometrics/fingerprint/aidl/default/VirtualHal.cpp
+++ b/biometrics/fingerprint/aidl/default/VirtualHal.cpp
@@ -26,7 +26,7 @@
 #define LOG_TAG "FingerprintVirtualHalAidl"
 
 namespace aidl::android::hardware::biometrics::fingerprint {
-
+using AcquiredInfoAndVendorCode = virtualhal::AcquiredInfoAndVendorCode;
 using Tag = AcquiredInfoAndVendorCode::Tag;
 
 ::ndk::ScopedAStatus VirtualHal::setEnrollments(const std::vector<int32_t>& enrollments) {
@@ -41,8 +41,7 @@
     return ndk::ScopedAStatus::ok();
 }
 
-::ndk::ScopedAStatus VirtualHal::setNextEnrollment(
-        const ::aidl::android::hardware::biometrics::fingerprint::NextEnrollment& next_enrollment) {
+::ndk::ScopedAStatus VirtualHal::setNextEnrollment(const NextEnrollment& next_enrollment) {
     Fingerprint::cfg().sourcedFromAidl();
     std::ostringstream os;
     os << next_enrollment.id << ":";
@@ -333,4 +332,10 @@
     return ndk::ScopedAStatus::ok();
 }
 
+::ndk::ScopedAStatus VirtualHal::getFingerprintHal(
+        std::shared_ptr<::aidl::android::hardware::biometrics::fingerprint::IFingerprint>* pFp) {
+    LOG(INFO) << " calling getFingerprintHal in VirtualHal.cpp";
+    *pFp = mFp;
+    return ndk::ScopedAStatus::ok();
+}
 }  // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt b/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt
index e69de29..8c02a68 100644
--- a/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt
+++ b/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt
@@ -0,0 +1,178 @@
+props {
+  owner: Vendor
+  module: "android.fingerprint.virt.FingerprintHalProperties"
+  prop {
+    api_name: "authenticator_id"
+    type: Long
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.authenticator_id"
+  }
+  prop {
+    api_name: "challenge"
+    type: Long
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.challenge"
+  }
+  prop {
+    api_name: "control_illumination"
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.udfps.control_illumination"
+  }
+  prop {
+    api_name: "detect_interaction"
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.detect_interaction"
+  }
+  prop {
+    api_name: "display_touch"
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.udfps.display_touch"
+  }
+  prop {
+    api_name: "enrollment_hit"
+    type: Integer
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.enrollment_hit"
+  }
+  prop {
+    api_name: "enrollments"
+    type: IntegerList
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.enrollments"
+  }
+  prop {
+    api_name: "lockout"
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.lockout"
+  }
+  prop {
+    api_name: "lockout_enable"
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.lockout_enable"
+  }
+  prop {
+    api_name: "lockout_permanent_threshold"
+    type: Integer
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.lockout_permanent_threshold"
+  }
+  prop {
+    api_name: "lockout_timed_duration"
+    type: Integer
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.lockout_timed_duration"
+  }
+  prop {
+    api_name: "lockout_timed_threshold"
+    type: Integer
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.lockout_timed_threshold"
+  }
+  prop {
+    api_name: "max_enrollments"
+    type: Integer
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.max_enrollments"
+  }
+  prop {
+    api_name: "navigation_guesture"
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.navigation_guesture"
+  }
+  prop {
+    api_name: "next_enrollment"
+    type: String
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.next_enrollment"
+  }
+  prop {
+    api_name: "operation_authenticate_acquired"
+    type: String
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.operation_authenticate_acquired"
+  }
+  prop {
+    api_name: "operation_authenticate_duration"
+    type: Integer
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.operation_authenticate_duration"
+  }
+  prop {
+    api_name: "operation_authenticate_error"
+    type: Integer
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.operation_authenticate_error"
+  }
+  prop {
+    api_name: "operation_authenticate_fails"
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.operation_authenticate_fails"
+  }
+  prop {
+    api_name: "operation_authenticate_latency"
+    type: IntegerList
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.operation_authenticate_latency"
+  }
+  prop {
+    api_name: "operation_detect_interaction_acquired"
+    type: String
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_acquired"
+  }
+  prop {
+    api_name: "operation_detect_interaction_duration"
+    type: Integer
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_duration"
+  }
+  prop {
+    api_name: "operation_detect_interaction_error"
+    type: Integer
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_error"
+  }
+  prop {
+    api_name: "operation_detect_interaction_latency"
+    type: IntegerList
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_latency"
+  }
+  prop {
+    api_name: "operation_enroll_error"
+    type: Integer
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.operation_enroll_error"
+  }
+  prop {
+    api_name: "operation_enroll_latency"
+    type: IntegerList
+    access: ReadWrite
+    prop_name: "vendor.fingerprint.virtual.operation_enroll_latency"
+  }
+  prop {
+    api_name: "sensor_id"
+    type: Integer
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.sensor_id"
+  }
+  prop {
+    api_name: "sensor_location"
+    type: String
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.sensor_location"
+  }
+  prop {
+    api_name: "sensor_strength"
+    type: Integer
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.sensor_strength"
+  }
+  prop {
+    api_name: "type"
+    type: String
+    access: ReadWrite
+    prop_name: "persist.vendor.fingerprint.virtual.type"
+    enum_values: "default|rear|udfps|side"
+  }
+}
diff --git a/biometrics/fingerprint/aidl/default/fingerprint-default.rc b/biometrics/fingerprint/aidl/default/fingerprint-default.rc
new file mode 100644
index 0000000..7e46bc1
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/fingerprint-default.rc
@@ -0,0 +1,7 @@
+service vendor.fingerprint-default /vendor/bin/hw/android.hardware.biometrics.fingerprint-service.default default
+    class hal
+    user nobody
+    group nobody
+    interface aidl android.hardware.biometrics.fingerprint.IFingerprint/default
+    oneshot
+    disabled
diff --git a/biometrics/fingerprint/aidl/default/fingerprint-default.xml b/biometrics/fingerprint/aidl/default/fingerprint-default.xml
new file mode 100644
index 0000000..d140459
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/fingerprint-default.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.biometrics.fingerprint</name>
+        <version>4</version>
+        <interface>
+          <name>IFingerprint</name>
+          <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/biometrics/fingerprint/aidl/default/fingerprint-example.rc b/biometrics/fingerprint/aidl/default/fingerprint-example.rc
deleted file mode 100644
index da4ea45..0000000
--- a/biometrics/fingerprint/aidl/default/fingerprint-example.rc
+++ /dev/null
@@ -1,7 +0,0 @@
-service vendor.fingerprint-example /apex/com.android.hardware.biometrics.fingerprint.virtual/bin/hw/android.hardware.biometrics.fingerprint-service.example
-    class hal
-    user nobody
-    group nobody
-    interface aidl android.hardware.biometrics.fingerprint.IFingerprint/virtual
-    oneshot
-    disabled
diff --git a/biometrics/fingerprint/aidl/default/fingerprint-example.xml b/biometrics/fingerprint/aidl/default/fingerprint-example.xml
deleted file mode 100644
index ee529e9..0000000
--- a/biometrics/fingerprint/aidl/default/fingerprint-example.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<manifest version="1.0" type="device">
-    <hal format="aidl">
-        <name>android.hardware.biometrics.fingerprint</name>
-        <version>5</version>
-        <fqname>IFingerprint/virtual</fqname>
-    </hal>
-</manifest>
diff --git a/biometrics/fingerprint/aidl/default/fingerprint-virtual.rc b/biometrics/fingerprint/aidl/default/fingerprint-virtual.rc
new file mode 100644
index 0000000..5d1506c
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/fingerprint-virtual.rc
@@ -0,0 +1,7 @@
+service fingerprint-virtual /apex/com.android.hardware.biometrics.fingerprint.virtual/bin/hw/android.hardware.biometrics.fingerprint-service.example virtual
+    class hal
+    user nobody
+    group nobody
+    interface aidl android.hardware.biometrics.fingerprint.virtualhal.IVirtualHal/virtual
+    oneshot
+    disabled
diff --git a/biometrics/fingerprint/aidl/default/fingerprint.sysprop b/biometrics/fingerprint/aidl/default/fingerprint.sysprop
index 6a6c297..eb33432 100644
--- a/biometrics/fingerprint/aidl/default/fingerprint.sysprop
+++ b/biometrics/fingerprint/aidl/default/fingerprint.sysprop
@@ -7,7 +7,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.type"
     type: String
-    scope: Internal
+    scope: Public
     access: ReadWrite
     enum_values: "default|rear|udfps|side"
     api_name: "type"
@@ -17,7 +17,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.enrollments"
     type: IntegerList
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "enrollments"
 }
@@ -27,7 +27,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.enrollment_hit"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "enrollment_hit"
 }
@@ -42,7 +42,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.next_enrollment"
     type: String
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "next_enrollment"
 }
@@ -51,7 +51,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.authenticator_id"
     type: Long
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "authenticator_id"
 }
@@ -60,7 +60,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.challenge"
     type: Long
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "challenge"
 }
@@ -69,7 +69,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.operation_authenticate_fails"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_authenticate_fails"
 }
@@ -82,7 +82,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_error"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_detect_interaction_error"
 }
@@ -91,7 +91,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.operation_enroll_error"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_enroll_error"
 }
@@ -104,7 +104,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.operation_authenticate_latency"
     type: IntegerList
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_authenticate_latency"
 }
@@ -114,7 +114,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_latency"
     type: IntegerList
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_detect_interaction_latency"
 }
@@ -124,7 +124,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.operation_enroll_latency"
     type: IntegerList
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_enroll_latency"
 }
@@ -134,7 +134,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.operation_authenticate_duration"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_authenticate_duration"
 }
@@ -143,7 +143,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.operation_authenticate_error"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_authenticate_error"
 }
@@ -153,7 +153,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.sensor_location"
     type: String
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "sensor_location"
 }
@@ -162,7 +162,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.operation_authenticate_acquired"
     type: String
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_authenticate_acquired"
 }
@@ -172,7 +172,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_duration"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_detect_interaction_duration"
 }
@@ -184,7 +184,7 @@
 prop {
     prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_acquired"
     type: String
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "operation_detect_interaction_acquired"
 }
@@ -193,7 +193,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.sensor_id"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "sensor_id"
 }
@@ -203,7 +203,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.sensor_strength"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "sensor_strength"
 }
@@ -213,7 +213,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.max_enrollments"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "max_enrollments"
 }
@@ -222,7 +222,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.navigation_guesture"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "navigation_guesture"
 }
@@ -231,7 +231,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.detect_interaction"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "detect_interaction"
 }
@@ -240,7 +240,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.udfps.display_touch"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "display_touch"
 }
@@ -249,7 +249,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.udfps.control_illumination"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "control_illumination"
 }
@@ -258,7 +258,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.lockout"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "lockout"
 }
@@ -267,7 +267,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.lockout_enable"
     type: Boolean
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "lockout_enable"
 }
@@ -276,7 +276,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.lockout_timed_threshold"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "lockout_timed_threshold"
 }
@@ -285,7 +285,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.lockout_timed_duration"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "lockout_timed_duration"
 }
@@ -294,7 +294,7 @@
 prop {
     prop_name: "persist.vendor.fingerprint.virtual.lockout_permanent_threshold"
     type: Integer
-    scope: Internal
+    scope: Public
     access: ReadWrite
     api_name: "lockout_permanent_threshold"
 }
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
index 0d53575..362d0df 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
@@ -110,7 +110,7 @@
     std::pair<Error, int32_t> convertError(int32_t code);
     int32_t getRandomInRange(int32_t bound1, int32_t bound2);
     bool checkSensorLockout(ISessionCallback*);
-    void clearLockout(ISessionCallback* cb);
+    void clearLockout(ISessionCallback* cb, bool dueToTimeout = false);
     void waitForFingerDown(ISessionCallback* cb, const std::future<void>& cancel);
 
     FakeLockoutTracker mLockoutTracker;
diff --git a/biometrics/fingerprint/aidl/default/include/FakeLockoutTracker.h b/biometrics/fingerprint/aidl/default/include/FakeLockoutTracker.h
index a1b6128..a7f2f8e 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeLockoutTracker.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeLockoutTracker.h
@@ -24,12 +24,12 @@
 
 class FakeLockoutTracker {
   public:
-    FakeLockoutTracker() : mFailedCount(0) {}
+    FakeLockoutTracker() : mFailedCount(0), mFailedCountTimed(0) {}
     ~FakeLockoutTracker() {}
 
     enum class LockoutMode : int8_t { kNone = 0, kTimed, kPermanent };
 
-    void reset();
+    void reset(bool dueToTimeout = false);
     LockoutMode getMode();
     void addFailedAttempt();
     int64_t getLockoutTimeLeft();
@@ -44,6 +44,7 @@
 
   private:
     int32_t mFailedCount;
+    int32_t mFailedCountTimed;
     int64_t mLockoutTimedStart;
     LockoutMode mCurrentMode;
 };
diff --git a/biometrics/fingerprint/aidl/default/include/VirtualHal.h b/biometrics/fingerprint/aidl/default/include/VirtualHal.h
index e5f62fc..5488383 100644
--- a/biometrics/fingerprint/aidl/default/include/VirtualHal.h
+++ b/biometrics/fingerprint/aidl/default/include/VirtualHal.h
@@ -16,21 +16,21 @@
 
 #pragma once
 
-#include <aidl/android/hardware/biometrics/fingerprint/BnVirtualHal.h>
+#include <aidl/android/hardware/biometrics/fingerprint/virtualhal/BnVirtualHal.h>
 
 #include "Fingerprint.h"
 
 namespace aidl::android::hardware::biometrics::fingerprint {
 
+using namespace virtualhal;
+
 class VirtualHal : public BnVirtualHal {
   public:
-    VirtualHal(Fingerprint* fp) : mFp(fp) {}
+    VirtualHal(std::shared_ptr<Fingerprint> fp) : mFp(fp) {}
 
     ::ndk::ScopedAStatus setEnrollments(const std::vector<int32_t>& in_id) override;
     ::ndk::ScopedAStatus setEnrollmentHit(int32_t in_hit_id) override;
-    ::ndk::ScopedAStatus setNextEnrollment(
-            const ::aidl::android::hardware::biometrics::fingerprint::NextEnrollment&
-                    in_next_enrollment) override;
+    ::ndk::ScopedAStatus setNextEnrollment(const NextEnrollment& in_next_enrollment) override;
     ::ndk::ScopedAStatus setAuthenticatorId(int64_t in_id) override;
     ::ndk::ScopedAStatus setChallenge(int64_t in_challenge) override;
     ::ndk::ScopedAStatus setOperationAuthenticateFails(bool in_fail) override;
@@ -67,12 +67,15 @@
     ::ndk::ScopedAStatus setDetectInteraction(bool in_v) override;
     ::ndk::ScopedAStatus setDisplayTouch(bool in_v) override;
     ::ndk::ScopedAStatus setControlIllumination(bool in_v) override;
+    ::ndk::ScopedAStatus getFingerprintHal(
+            std::shared_ptr<::aidl::android::hardware::biometrics::fingerprint::IFingerprint>*
+                    _aidl_return);
 
   private:
     OptIntVec intVec2OptIntVec(const std::vector<int32_t>& intVec);
     OptIntVec acquiredInfoVec2OptIntVec(const std::vector<AcquiredInfoAndVendorCode>& intVec);
     ::ndk::ScopedAStatus sanityCheckLatency(const std::vector<int32_t>& in_latency);
-    Fingerprint* mFp;
+    std::shared_ptr<Fingerprint> mFp;
 };
 
 }  // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/main.cpp b/biometrics/fingerprint/aidl/default/main.cpp
index ba0c8ec..8ca44d6 100644
--- a/biometrics/fingerprint/aidl/default/main.cpp
+++ b/biometrics/fingerprint/aidl/default/main.cpp
@@ -24,21 +24,38 @@
 using aidl::android::hardware::biometrics::fingerprint::Fingerprint;
 using aidl::android::hardware::biometrics::fingerprint::VirtualHal;
 
-int main() {
-    LOG(INFO) << "Fingerprint HAL started";
+int main(int argc, char** argv) {
+    if (argc < 2) {
+        LOG(ERROR) << "Missing argument -> exiting";
+        return EXIT_FAILURE;
+    }
+
+    LOG(INFO) << "Fingerprint HAL started: " << argv[1];
     ABinderProcess_setThreadPoolMaxThreadCount(0);
     std::shared_ptr<Fingerprint> hal = ndk::SharedRefBase::make<Fingerprint>();
-    auto binder = hal->asBinder();
-
-    std::shared_ptr<VirtualHal> hal_ext = ndk::SharedRefBase::make<VirtualHal>(hal.get());
-    auto binder_ext = hal_ext->asBinder();
+    std::shared_ptr<VirtualHal> hal_vhal = ndk::SharedRefBase::make<VirtualHal>(hal);
 
     if (hal->connected()) {
-        CHECK(STATUS_OK == AIBinder_setExtension(binder.get(), binder_ext.get()));
-        const std::string instance = std::string(Fingerprint::descriptor) + "/virtual";
-        binder_status_t status =
-                AServiceManager_registerLazyService(binder.get(), instance.c_str());
-        CHECK_EQ(status, STATUS_OK);
+        if (strcmp(argv[1], "default") == 0) {
+            const std::string instance = std::string(Fingerprint::descriptor) + "/default";
+            auto binder = hal->asBinder();
+            auto binder_ext = hal_vhal->asBinder();
+            CHECK(STATUS_OK == AIBinder_setExtension(binder.get(), binder_ext.get()));
+            binder_status_t status =
+                    AServiceManager_registerLazyService(binder.get(), instance.c_str());
+            CHECK_EQ(status, STATUS_OK);
+            LOG(INFO) << "started IFingerprint/default";
+        } else if (strcmp(argv[1], "virtual") == 0) {
+            const std::string instance = std::string(VirtualHal::descriptor) + "/virtual";
+            auto binder = hal_vhal->asBinder();
+            binder_status_t status =
+                    AServiceManager_registerLazyService(binder.get(), instance.c_str());
+            CHECK_EQ(status, STATUS_OK);
+            LOG(INFO) << "started IVirtualHal/virtual";
+        } else {
+            LOG(ERROR) << "Unexpected argument: " << argv[1];
+            return EXIT_FAILURE;
+        }
         AServiceManager_forceLazyServicesPersist(true);
     } else {
         LOG(ERROR) << "Fingerprint HAL is not connected";
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
index 3c12b6d..4c1277b 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
@@ -75,7 +75,7 @@
         prevTimeLeft = currTimeLeft;
     }
     ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
-    mLockoutTracker.reset();
+    mLockoutTracker.reset(true);
 }
 
 TEST_F(FakeLockoutTrackerTest, addFailedAttemptPermanent) {
diff --git a/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp b/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp
index 3fe0b2a..8ffc96b 100644
--- a/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp
@@ -35,7 +35,7 @@
   protected:
     void SetUp() override {
         mHal = ndk::SharedRefBase::make<Fingerprint>();
-        mVhal = ndk::SharedRefBase::make<VirtualHal>(mHal.get());
+        mVhal = ndk::SharedRefBase::make<VirtualHal>(mHal);
         ASSERT_TRUE(mVhal != nullptr);
         mHal->resetConfigToDefault();
     }
diff --git a/biometrics/fingerprint/aidl/vts/Android.bp b/biometrics/fingerprint/aidl/vts/Android.bp
index fc32fe6..628f03f 100644
--- a/biometrics/fingerprint/aidl/vts/Android.bp
+++ b/biometrics/fingerprint/aidl/vts/Android.bp
@@ -16,8 +16,8 @@
     ],
     srcs: ["VtsHalBiometricsFingerprintTargetTest.cpp"],
     static_libs: [
-        "android.hardware.biometrics.common-V3-ndk",
-        "android.hardware.biometrics.fingerprint-V3-ndk",
+        "android.hardware.biometrics.common-V4-ndk",
+        "android.hardware.biometrics.fingerprint-V4-ndk",
         "android.hardware.keymaster-V4-ndk",
     ],
     shared_libs: [
diff --git a/bluetooth/1.0/Android.bp b/bluetooth/1.0/Android.bp
index bd1ca69..3ffc203 100644
--- a/bluetooth/1.0/Android.bp
+++ b/bluetooth/1.0/Android.bp
@@ -23,6 +23,6 @@
     gen_java: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.btservices",
+        "com.android.bt",
     ],
 }
diff --git a/bluetooth/1.0/vts/functional/Android.bp b/bluetooth/1.0/vts/functional/Android.bp
index 768142c..e68df09 100644
--- a/bluetooth/1.0/vts/functional/Android.bp
+++ b/bluetooth/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_bluetooth",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
@@ -29,7 +30,6 @@
     srcs: ["VtsHalBluetoothV1_0TargetTest.cpp"],
     static_libs: [
         "android.hardware.bluetooth@1.0",
-        "libbluetooth-types",
     ],
     test_config: "VtsHalBluetoothV1_0TargetTest.xml",
     test_suites: [
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
index 82dda61..d0edfad 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
@@ -20,7 +20,6 @@
 #include <android/hardware/bluetooth/1.0/IBluetoothHci.h>
 #include <android/hardware/bluetooth/1.0/IBluetoothHciCallbacks.h>
 #include <android/hardware/bluetooth/1.0/types.h>
-#include <hardware/bluetooth.h>
 #include <utils/Log.h>
 
 #include <VtsHalHidlTargetCallbackBase.h>
diff --git a/bluetooth/1.1/Android.bp b/bluetooth/1.1/Android.bp
index f8a05f1..9c65b62 100644
--- a/bluetooth/1.1/Android.bp
+++ b/bluetooth/1.1/Android.bp
@@ -23,6 +23,6 @@
     gen_java: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.btservices",
+        "com.android.bt",
     ],
 }
diff --git a/bluetooth/1.1/vts/functional/Android.bp b/bluetooth/1.1/vts/functional/Android.bp
index 7f56647..27d50f5 100644
--- a/bluetooth/1.1/vts/functional/Android.bp
+++ b/bluetooth/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_bluetooth",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
@@ -30,7 +31,6 @@
     static_libs: [
         "android.hardware.bluetooth@1.1",
         "android.hardware.bluetooth@1.0",
-        "libbluetooth-types",
     ],
     test_config: "VtsHalBluetoothV1_1TargetTest.xml",
     test_suites: ["general-tests", "vts"],
diff --git a/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.cpp b/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.cpp
index 687765f..37b41c6 100644
--- a/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.cpp
+++ b/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.cpp
@@ -20,7 +20,6 @@
 #include <android/hardware/bluetooth/1.0/types.h>
 #include <android/hardware/bluetooth/1.1/IBluetoothHci.h>
 #include <android/hardware/bluetooth/1.1/IBluetoothHciCallbacks.h>
-#include <hardware/bluetooth.h>
 #include <utils/Log.h>
 
 #include <VtsHalHidlTargetCallbackBase.h>
diff --git a/bluetooth/OWNERS b/bluetooth/OWNERS
index f401b8c..df250c8 100644
--- a/bluetooth/OWNERS
+++ b/bluetooth/OWNERS
@@ -1,5 +1,5 @@
 # Bug component: 27441
 
+asoulier@google.com
 henrichataing@google.com
-mylesgw@google.com
 siyuanh@google.com
diff --git a/bluetooth/aidl/Android.bp b/bluetooth/aidl/Android.bp
index c6a592f..0daecf7 100644
--- a/bluetooth/aidl/Android.bp
+++ b/bluetooth/aidl/Android.bp
@@ -23,13 +23,16 @@
             // translate code.
             enabled: true,
         },
+        rust: {
+            enabled: true,
+        },
         java: {
             sdk_version: "module_current",
         },
         ndk: {
             apex_available: [
                 "//apex_available:platform",
-                "com.android.btservices",
+                "com.android.bt",
             ],
             min_sdk_version: "33",
         },
diff --git a/bluetooth/aidl/vts/Android.bp b/bluetooth/aidl/vts/Android.bp
index c69ced4..a08bdfc 100644
--- a/bluetooth/aidl/vts/Android.bp
+++ b/bluetooth/aidl/vts/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_bluetooth",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/bluetooth/audio/2.0/Android.bp b/bluetooth/audio/2.0/Android.bp
index 725ec11..61f9a35 100644
--- a/bluetooth/audio/2.0/Android.bp
+++ b/bluetooth/audio/2.0/Android.bp
@@ -26,6 +26,6 @@
     gen_java: false,
     apex_available: [
         "//apex_available:platform",
-        "com.android.btservices",
+        "com.android.bt",
     ],
 }
diff --git a/bluetooth/audio/2.0/vts/functional/Android.bp b/bluetooth/audio/2.0/vts/functional/Android.bp
index f5cb956..65ad8d0 100644
--- a/bluetooth/audio/2.0/vts/functional/Android.bp
+++ b/bluetooth/audio/2.0/vts/functional/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_bluetooth",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/bluetooth/audio/2.1/Android.bp b/bluetooth/audio/2.1/Android.bp
index 4ca0bef..4d01a00 100644
--- a/bluetooth/audio/2.1/Android.bp
+++ b/bluetooth/audio/2.1/Android.bp
@@ -25,7 +25,7 @@
     ],
     apex_available: [
         "//apex_available:platform",
-        "com.android.btservices",
+        "com.android.bt",
     ],
     gen_java: false,
 }
diff --git a/bluetooth/audio/2.1/vts/functional/Android.bp b/bluetooth/audio/2.1/vts/functional/Android.bp
index cea7326..de858fc 100644
--- a/bluetooth/audio/2.1/vts/functional/Android.bp
+++ b/bluetooth/audio/2.1/vts/functional/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_bluetooth",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
index ae55fa9..6d4edb1 100644
--- a/bluetooth/audio/aidl/Android.bp
+++ b/bluetooth/audio/aidl/Android.bp
@@ -38,6 +38,9 @@
         cpp: {
             enabled: false,
         },
+        rust: {
+            enabled: true,
+        },
         java: {
             sdk_version: "module_current",
             enabled: false,
@@ -45,7 +48,7 @@
         ndk: {
             apex_available: [
                 "//apex_available:platform",
-                "com.android.btservices",
+                "com.android.bt",
             ],
             min_sdk_version: "31",
         },
@@ -86,7 +89,6 @@
 
     ],
     frozen: false,
-
 }
 
 // Note: This should always be one version ahead of the last frozen version
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl
index 58710ef..2872362 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl
@@ -38,6 +38,7 @@
   android.hardware.bluetooth.audio.AudioLocation supportedChannel;
   int channelCountPerStream;
   android.hardware.bluetooth.audio.BroadcastCapability.LeAudioCodecCapabilities leAudioCodecCapabilities;
+  @nullable android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv.AudioChannelAllocation audioLocation;
   @VintfStability
   parcelable VendorCapabilities {
     ParcelableHolder extension;
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl
index 60c276b..93c3d8c 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl
@@ -59,8 +59,10 @@
     int bitmask;
     const int US7500 = 0x01;
     const int US10000 = 0x02;
+    const int US20000 = 0x04;
     const int US7500PREFERRED = 0x10;
     const int US10000PREFERRED = 0x20;
+    const int US20000PREFERRED = 0x40;
   }
   parcelable SupportedAudioChannelCounts {
     int bitmask;
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl
index 943d396..97fcd1f 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl
@@ -59,6 +59,7 @@
   enum FrameDuration {
     US7500 = 0x00,
     US10000 = 0x01,
+    US20000 = 0x02,
   }
   parcelable AudioChannelAllocation {
     int bitmask;
@@ -91,6 +92,7 @@
     const int FRONT_RIGHT_WIDE = 0x02000000;
     const int LEFT_SURROUND = 0x04000000;
     const int RIGHT_SURROUND = 0x08000000;
+    const int MONO = 0x00000000;
   }
   parcelable OctetsPerCodecFrame {
     int value;
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
index 031ee67..0613f6c 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
@@ -37,6 +37,7 @@
   android.hardware.bluetooth.audio.Lc3Configuration lc3Config;
   android.hardware.bluetooth.audio.LeAudioCodecConfiguration.VendorConfiguration vendorConfig;
   android.hardware.bluetooth.audio.AptxAdaptiveLeConfiguration aptxAdaptiveLeConfig;
+  android.hardware.bluetooth.audio.OpusConfiguration opusConfig;
   @VintfStability
   parcelable VendorConfiguration {
     ParcelableHolder extension;
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastCapability.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastCapability.aidl
index 894a2f3..6ed0e56 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastCapability.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastCapability.aidl
@@ -39,6 +39,7 @@
   int deviceCount;
   int channelCountPerDevice;
   android.hardware.bluetooth.audio.UnicastCapability.LeAudioCodecCapabilities leAudioCodecCapabilities;
+  @nullable android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv.AudioChannelAllocation audioLocation;
   @VintfStability
   parcelable VendorCapabilities {
     ParcelableHolder extension;
@@ -48,5 +49,6 @@
     android.hardware.bluetooth.audio.Lc3Capabilities lc3Capabilities;
     android.hardware.bluetooth.audio.UnicastCapability.VendorCapabilities vendorCapabillities;
     android.hardware.bluetooth.audio.AptxAdaptiveLeCapabilities aptxAdaptiveLeCapabilities;
+    android.hardware.bluetooth.audio.OpusCapabilities opusCapabilities;
   }
 }
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl
index f1301fb..db3c10e 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl
@@ -17,6 +17,7 @@
 package android.hardware.bluetooth.audio;
 
 import android.hardware.bluetooth.audio.AudioLocation;
+import android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv.AudioChannelAllocation;
 import android.hardware.bluetooth.audio.CodecType;
 import android.hardware.bluetooth.audio.Lc3Capabilities;
 
@@ -35,8 +36,11 @@
         @nullable VendorCapabilities[] vendorCapabillities;
     }
     CodecType codecType;
+    // @deprecated use audioLocation if present.
     AudioLocation supportedChannel;
     // Supported channel count for each stream
     int channelCountPerStream;
     LeAudioCodecCapabilities leAudioCodecCapabilities;
+    // The new audio location type, replacing supportedChannel
+    @nullable AudioChannelAllocation audioLocation;
 }
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl
index fa302e3..94f0544 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.aidl
@@ -50,9 +50,11 @@
     parcelable SupportedFrameDurations {
         const int US7500 = 0x01;
         const int US10000 = 0x02;
+        const int US20000 = 0x04;
         /* Bits 2-3 are RFU */
         const int US7500PREFERRED = 0x10;
         const int US10000PREFERRED = 0x20;
+        const int US20000PREFERRED = 0x40;
 
         /* 8 bit wide bit mask */
         int bitmask;
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl
index c099ebe..2835325 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.aidl
@@ -43,9 +43,11 @@
     enum FrameDuration {
         US7500 = 0x00,
         US10000 = 0x01,
+        US20000 = 0x02,
     }
 
     parcelable AudioChannelAllocation {
+        // @deprecated use MONO instead.
         const int NOT_ALLOWED = 0x00000000;
         const int FRONT_LEFT = 0x00000001;
         const int FRONT_RIGHT = 0x00000002;
@@ -75,6 +77,7 @@
         const int FRONT_RIGHT_WIDE = 0x02000000;
         const int LEFT_SURROUND = 0x04000000;
         const int RIGHT_SURROUND = 0x08000000;
+        const int MONO = 0x00000000;
 
         // Bit mask of Audio Locations
         int bitmask;
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
index 7ce6ff3..20e6c0c 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
@@ -16,8 +16,9 @@
 
 package android.hardware.bluetooth.audio;
 
-import android.hardware.bluetooth.audio.Lc3Configuration;
 import android.hardware.bluetooth.audio.AptxAdaptiveLeConfiguration;
+import android.hardware.bluetooth.audio.Lc3Configuration;
+import android.hardware.bluetooth.audio.OpusConfiguration;
 
 @VintfStability
 union LeAudioCodecConfiguration {
@@ -28,4 +29,5 @@
     Lc3Configuration lc3Config;
     VendorConfiguration vendorConfig;
     AptxAdaptiveLeConfiguration aptxAdaptiveLeConfig;
+    OpusConfiguration opusConfig;
 }
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastCapability.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastCapability.aidl
index 07688a7..9f33672 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastCapability.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastCapability.aidl
@@ -16,10 +16,12 @@
 
 package android.hardware.bluetooth.audio;
 
+import android.hardware.bluetooth.audio.AptxAdaptiveLeCapabilities;
 import android.hardware.bluetooth.audio.AudioLocation;
+import android.hardware.bluetooth.audio.CodecSpecificConfigurationLtv.AudioChannelAllocation;
 import android.hardware.bluetooth.audio.CodecType;
 import android.hardware.bluetooth.audio.Lc3Capabilities;
-import android.hardware.bluetooth.audio.AptxAdaptiveLeCapabilities;
+import android.hardware.bluetooth.audio.OpusCapabilities;
 
 /**
  * Used to specify the le audio unicast codec capabilities for hardware offload.
@@ -35,12 +37,16 @@
         Lc3Capabilities lc3Capabilities;
         VendorCapabilities vendorCapabillities;
         AptxAdaptiveLeCapabilities aptxAdaptiveLeCapabilities;
+        OpusCapabilities opusCapabilities;
     }
     CodecType codecType;
+    // @deprecated use audioLocation if present.
     AudioLocation supportedChannel;
     // The number of connected device
     int deviceCount;
     // Supported channel count for each device
     int channelCountPerDevice;
     LeAudioCodecCapabilities leAudioCodecCapabilities;
+    // The new audio location type, replacing supportedChannel
+    @nullable AudioChannelAllocation audioLocation;
 }
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
index 6783c0f..3f1f5f6 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -82,6 +82,8 @@
          CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500},
         {CodecSpecificConfigurationLtv::FrameDuration::US10000,
          CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US10000},
+        {CodecSpecificConfigurationLtv::FrameDuration::US20000,
+         CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US20000},
 };
 
 std::map<int32_t, CodecSpecificConfigurationLtv::SamplingFrequency>
@@ -121,6 +123,40 @@
   return (sessionType == session_type_);
 }
 
+std::string getSettingOutputString(
+    IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting) {
+  std::stringstream ss;
+  std::string name = "";
+  if (!setting.sinkAseConfiguration.has_value() &&
+      !setting.sourceAseConfiguration.has_value())
+    return "";
+  std::vector<
+      std::optional<LeAudioAseConfigurationSetting::AseDirectionConfiguration>>*
+      directionAseConfiguration;
+  if (setting.sinkAseConfiguration.has_value() &&
+      !setting.sinkAseConfiguration.value().empty())
+    directionAseConfiguration = &setting.sinkAseConfiguration.value();
+  else
+    directionAseConfiguration = &setting.sourceAseConfiguration.value();
+  for (auto& aseConfiguration : *directionAseConfiguration) {
+    if (aseConfiguration.has_value() &&
+        aseConfiguration.value().aseConfiguration.metadata.has_value()) {
+      for (auto& meta :
+           aseConfiguration.value().aseConfiguration.metadata.value()) {
+        if (meta.has_value() &&
+            meta.value().getTag() == MetadataLtv::vendorSpecific) {
+          auto k = meta.value().get<MetadataLtv::vendorSpecific>().opaqueValue;
+          name = std::string(k.begin(), k.end());
+          break;
+        }
+      }
+    }
+  }
+
+  ss << "setting name: " << name << ", setting: " << setting.toString();
+  return ss.str();
+}
+
 ndk::ScopedAStatus LeAudioOffloadAudioProvider::startSession(
     const std::shared_ptr<IBluetoothAudioPort>& host_if,
     const AudioConfiguration& audio_config,
@@ -218,15 +254,24 @@
   return false;
 }
 
+int getCountFromBitmask(int bitmask) {
+  return std::bitset<32>(bitmask).count();
+}
+
 bool LeAudioOffloadAudioProvider::isMatchedAudioChannel(
-    CodecSpecificConfigurationLtv::AudioChannelAllocation&
-    /*cfg_channel*/,
+    CodecSpecificConfigurationLtv::AudioChannelAllocation& cfg_channel,
     CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts&
-    /*capability_channel*/) {
-  // Simply ignore.
-  // Later can use additional capabilities to match requirement.
-  bool isMatched = true;
-  return isMatched;
+        capability_channel) {
+  int count = getCountFromBitmask(cfg_channel.bitmask);
+  if (count == 1 &&
+      !(capability_channel.bitmask &
+        CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts::ONE))
+    return false;
+  if (count == 2 &&
+      !(capability_channel.bitmask &
+        CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts::TWO))
+    return false;
+  return true;
 }
 
 bool LeAudioOffloadAudioProvider::isMatchedCodecFramesPerSDU(
@@ -322,12 +367,6 @@
   return true;
 }
 
-bool isMonoConfig(
-    CodecSpecificConfigurationLtv::AudioChannelAllocation allocation) {
-  auto channel_count = std::bitset<32>(allocation.bitmask);
-  return (channel_count.count() <= 1);
-}
-
 bool LeAudioOffloadAudioProvider::filterMatchedAseConfiguration(
     LeAudioAseConfiguration& setting_cfg,
     const LeAudioAseConfiguration& requirement_cfg) {
@@ -337,9 +376,6 @@
     if (!setting_cfg.codecId.has_value()) return false;
     if (!isMatchedValidCodec(setting_cfg.codecId.value(),
                              requirement_cfg.codecId.value())) {
-      LOG(WARNING) << __func__ << ": Doesn't match valid codec, cfg = "
-                   << setting_cfg.codecId.value().toString()
-                   << ", req = " << requirement_cfg.codecId.value().toString();
       return false;
     }
   }
@@ -347,9 +383,6 @@
   if (requirement_cfg.targetLatency !=
           LeAudioAseConfiguration::TargetLatency::UNDEFINED &&
       setting_cfg.targetLatency != requirement_cfg.targetLatency) {
-    LOG(WARNING) << __func__ << ": Doesn't match target latency, cfg = "
-                 << int(setting_cfg.targetLatency)
-                 << ", req = " << int(requirement_cfg.targetLatency);
     return false;
   }
   // Ignore PHY requirement
@@ -365,8 +398,6 @@
     auto cfg = cfg_tag_map.find(requirement_cfg.getTag());
     // Config not found for this requirement, cannot match
     if (cfg == cfg_tag_map.end()) {
-      LOG(WARNING) << __func__ << ": Config not found for the requirement "
-                   << requirement_cfg.toString();
       return false;
     }
 
@@ -377,10 +408,6 @@
       continue;
 
     if (cfg->second != requirement_cfg) {
-      LOG(WARNING) << __func__
-                   << ": Config doesn't match the requirement, cfg = "
-                   << cfg->second.toString()
-                   << ", req = " << requirement_cfg.toString();
       return false;
     }
   }
@@ -437,10 +464,6 @@
   return 0;
 }
 
-int getCountFromBitmask(int bitmask) {
-  return std::bitset<32>(bitmask).count();
-}
-
 std::optional<AseDirectionConfiguration> findValidMonoConfig(
     std::vector<AseDirectionConfiguration>& valid_direction_configurations,
     int bitmask) {
@@ -466,11 +489,11 @@
 std::vector<AseDirectionConfiguration> getValidConfigurationsFromAllocation(
     int req_allocation_bitmask,
     std::vector<AseDirectionConfiguration>& valid_direction_configurations,
-    bool is_exact) {
+    bool isExact) {
   // Prefer the same allocation_bitmask
   int channel_count = getCountFromBitmask(req_allocation_bitmask);
 
-  if (is_exact) {
+  if (isExact) {
     for (auto& cfg : valid_direction_configurations) {
       int cfg_bitmask =
           getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration);
@@ -505,14 +528,14 @@
   return {};
 }
 
+// Check and filter each index to see if it's a match.
 void LeAudioOffloadAudioProvider::filterRequirementAseDirectionConfiguration(
     std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
         direction_configurations,
     const std::vector<std::optional<AseDirectionRequirement>>& requirements,
     std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
         valid_direction_configurations,
-    bool is_exact) {
-  // For every requirement, find the matched ase configuration
+    bool isExact) {
   if (!direction_configurations.has_value()) return;
 
   if (!valid_direction_configurations.has_value()) {
@@ -520,37 +543,92 @@
         std::vector<std::optional<AseDirectionConfiguration>>();
   }
 
-  for (auto& requirement : requirements) {
-    if (!requirement.has_value()) continue;
-    auto req_allocation_bitmask = getLeAudioAseConfigurationAllocationBitmask(
-        requirement.value().aseConfiguration);
-    auto req_channel_count = getCountFromBitmask(req_allocation_bitmask);
-
-    auto temp = std::vector<AseDirectionConfiguration>();
-
-    for (auto direction_configuration : direction_configurations.value()) {
-      if (!direction_configuration.has_value()) continue;
+  if (isExact) {
+    // Exact matching process
+    // Need to respect the number of device
+    for (int i = 0; i < requirements.size(); ++i) {
+      auto requirement = requirements[i];
+      auto direction_configuration = direction_configurations.value()[i];
+      if (!direction_configuration.has_value()) {
+        valid_direction_configurations = std::nullopt;
+        return;
+      }
+      auto cfg = direction_configuration.value();
       if (!filterMatchedAseConfiguration(
-              direction_configuration.value().aseConfiguration,
-              requirement.value().aseConfiguration))
-        continue;
-      // Valid if match any requirement.
-      temp.push_back(direction_configuration.value());
-    }
-
-    // Get the best matching config based on channel allocation
-    auto total_cfg_channel_count = 0;
-    auto req_valid_configs = getValidConfigurationsFromAllocation(
-        req_allocation_bitmask, temp, is_exact);
-    // Count and check required channel counts
-    for (auto& cfg : req_valid_configs) {
-      total_cfg_channel_count += getCountFromBitmask(
-          getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration));
+              cfg.aseConfiguration, requirement.value().aseConfiguration)) {
+        valid_direction_configurations = std::nullopt;
+        return;  // No way to match
+      }
+      // For exact match, we require this direction to have the same allocation.
+      // If stereo, need stereo.
+      // If mono, need mono (modified to the correct required allocation)
+      auto req_allocation_bitmask = getLeAudioAseConfigurationAllocationBitmask(
+          requirement.value().aseConfiguration);
+      int req_channel_count = getCountFromBitmask(req_allocation_bitmask);
+      int cfg_bitmask =
+          getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration);
+      int cfg_channel_count = getCountFromBitmask(cfg_bitmask);
+      if (req_channel_count <= 1) {
+        // MONO case, is a match if also mono, modify to the same allocation
+        if (cfg_channel_count > 1) {
+          valid_direction_configurations = std::nullopt;
+          return;  // Not a match
+        }
+        // Modify the bitmask to be the same as the requirement
+        for (auto& codec_cfg : cfg.aseConfiguration.codecConfiguration) {
+          if (codec_cfg.getTag() ==
+              CodecSpecificConfigurationLtv::Tag::audioChannelAllocation) {
+            codec_cfg
+                .get<CodecSpecificConfigurationLtv::Tag::
+                         audioChannelAllocation>()
+                .bitmask = req_allocation_bitmask;
+            break;
+          }
+        }
+      } else {
+        // STEREO case, is a match if same allocation
+        if (req_allocation_bitmask != cfg_bitmask) {
+          valid_direction_configurations = std::nullopt;
+          return;  // Not a match
+        }
+      }
+      // Push to list if valid
       valid_direction_configurations.value().push_back(cfg);
     }
-    if (total_cfg_channel_count != req_channel_count) {
-      valid_direction_configurations = std::nullopt;
-      return;
+  } else {
+    // Loose matching process
+    for (auto& requirement : requirements) {
+      if (!requirement.has_value()) continue;
+      auto req_allocation_bitmask = getLeAudioAseConfigurationAllocationBitmask(
+          requirement.value().aseConfiguration);
+      auto req_channel_count = getCountFromBitmask(req_allocation_bitmask);
+
+      auto temp = std::vector<AseDirectionConfiguration>();
+
+      for (auto direction_configuration : direction_configurations.value()) {
+        if (!direction_configuration.has_value()) continue;
+        if (!filterMatchedAseConfiguration(
+                direction_configuration.value().aseConfiguration,
+                requirement.value().aseConfiguration))
+          continue;
+        // Valid if match any requirement.
+        temp.push_back(direction_configuration.value());
+      }
+
+      // Get the best matching config based on channel allocation
+      auto total_cfg_channel_count = 0;
+      auto req_valid_configs = getValidConfigurationsFromAllocation(
+          req_allocation_bitmask, temp, isExact);
+      // Count and check required channel counts
+      for (auto& cfg : req_valid_configs) {
+        total_cfg_channel_count += getCountFromBitmask(
+            getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration));
+        valid_direction_configurations.value().push_back(cfg);
+      }
+      if (total_cfg_channel_count != req_channel_count) {
+        valid_direction_configurations = std::nullopt;
+        return;
+      }
     }
   }
 }
@@ -564,7 +642,6 @@
     const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
     uint8_t direction) {
   // Create a new LeAudioAseConfigurationSetting and return
-  // For other direction will contain all settings
   LeAudioAseConfigurationSetting filtered_setting{
       .audioContext = setting.audioContext,
       .sinkAseConfiguration = setting.sinkAseConfiguration,
@@ -613,26 +690,40 @@
 LeAudioOffloadAudioProvider::getRequirementMatchedAseConfigurationSettings(
     IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
     const IBluetoothAudioProvider::LeAudioConfigurationRequirement& requirement,
-    bool is_exact) {
-  // Try to match context in metadata.
-  if ((setting.audioContext.bitmask & requirement.audioContext.bitmask) !=
-      requirement.audioContext.bitmask)
-    return std::nullopt;
-
-  // Further filter setting's context
-  setting.audioContext.bitmask &= requirement.audioContext.bitmask;
-
+    bool isExact) {
   // Create a new LeAudioAseConfigurationSetting to return
+  // Make context the same as the requirement
   LeAudioAseConfigurationSetting filtered_setting{
-      .audioContext = setting.audioContext,
+      .audioContext = requirement.audioContext,
       .packing = setting.packing,
       .flags = setting.flags,
   };
 
+  // The number of AseDirectionRequirement in the requirement
+  // is the number of device.
+
+  // The exact matching process is as follow:
+  // 1. Setting direction has the same number of cfg (ignore when null
+  // require)
+  // 2. For each index, it's a 1-1 filter / mapping.
+  if (isExact) {
+    if (requirement.sinkAseRequirement.has_value() &&
+        requirement.sinkAseRequirement.value().size() !=
+            setting.sinkAseConfiguration.value().size()) {
+      return std::nullopt;
+    }
+
+    if (requirement.sourceAseRequirement.has_value() &&
+        requirement.sourceAseRequirement.value().size() !=
+            setting.sourceAseConfiguration.value().size()) {
+      return std::nullopt;
+    }
+  }
+
   if (requirement.sinkAseRequirement.has_value()) {
     filterRequirementAseDirectionConfiguration(
         setting.sinkAseConfiguration, requirement.sinkAseRequirement.value(),
-        filtered_setting.sinkAseConfiguration, is_exact);
+        filtered_setting.sinkAseConfiguration, isExact);
     if (!filtered_setting.sinkAseConfiguration.has_value()) {
       return std::nullopt;
     }
@@ -642,7 +733,7 @@
     filterRequirementAseDirectionConfiguration(
         setting.sourceAseConfiguration,
         requirement.sourceAseRequirement.value(),
-        filtered_setting.sourceAseConfiguration, is_exact);
+        filtered_setting.sourceAseConfiguration, isExact);
     if (!filtered_setting.sourceAseConfiguration.has_value()) {
       return std::nullopt;
     }
@@ -651,47 +742,63 @@
   return filtered_setting;
 }
 
-std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+std::optional<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
 LeAudioOffloadAudioProvider::matchWithRequirement(
     std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>&
         matched_ase_configuration_settings,
-    const std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
-        in_requirements,
-    bool is_exact) {
-  // Each requirement will match with a valid setting
-  std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> result;
-  for (auto& requirement : in_requirements) {
-    LOG(INFO) << __func__ << ": Trying to match for the requirement "
-              << requirement.toString();
-    bool is_matched = false;
-
-    for (auto& setting : matched_ase_configuration_settings) {
-      auto filtered_ase_configuration_setting =
-          getRequirementMatchedAseConfigurationSettings(setting, requirement,
-                                                        is_exact);
-      if (filtered_ase_configuration_setting.has_value()) {
-        result.push_back(filtered_ase_configuration_setting.value());
-        LOG(INFO) << __func__ << ": Result = "
-                  << filtered_ase_configuration_setting.value().toString();
-        // Found a matched setting, ignore other settings
-        is_matched = true;
-        break;
-      }
+    const IBluetoothAudioProvider::LeAudioConfigurationRequirement& requirement,
+    bool isMatchContext, bool isExact, bool isMatchFlags) {
+  LOG(INFO) << __func__ << ": Trying to match for the requirement "
+            << requirement.toString() << ", match context = " << isMatchContext
+            << ", match exact = " << isExact
+            << ", match flags = " << isMatchFlags;
+  // Don't have to match with flag if requirements don't have flags.
+  auto requirement_flags_bitmask = 0;
+  if (isMatchFlags) {
+    if (!requirement.flags.has_value()) return std::nullopt;
+    requirement_flags_bitmask = requirement.flags.value().bitmask;
+  }
+  for (auto& setting : matched_ase_configuration_settings) {
+    // Try to match context.
+    if (isMatchContext) {
+      if ((setting.audioContext.bitmask & requirement.audioContext.bitmask) !=
+          requirement.audioContext.bitmask)
+        continue;
+      LOG(DEBUG) << __func__ << ": Setting with matched context: "
+                 << getSettingOutputString(setting);
     }
-    if (!is_matched) {
-      // If cannot satisfy this requirement, return an empty result
-      LOG(WARNING) << __func__ << ": Cannot match the requirement "
-                   << requirement.toString();
-      result.clear();
-      break;
+
+    // Try to match configuration flags
+    if (isMatchFlags) {
+      if (!setting.flags.has_value()) continue;
+      if ((setting.flags.value().bitmask & requirement_flags_bitmask) !=
+          requirement_flags_bitmask)
+        continue;
+      LOG(DEBUG) << __func__ << ": Setting with matched flags: "
+                 << getSettingOutputString(setting);
+    }
+
+    auto filtered_ase_configuration_setting =
+        getRequirementMatchedAseConfigurationSettings(setting, requirement,
+                                                      isExact);
+    if (filtered_ase_configuration_setting.has_value()) {
+      LOG(INFO) << __func__ << ": Result found: "
+                << getSettingOutputString(
+                       filtered_ase_configuration_setting.value());
+      // Found a matched setting, ignore other settings
+      return filtered_ase_configuration_setting;
     }
   }
-  return result;
+  // If cannot satisfy this requirement, return nullopt
+  LOG(WARNING) << __func__ << ": Cannot match the requirement "
+               << requirement.toString()
+               << ", match context = " << isMatchContext;
+  return std::nullopt;
 }
 
 // For each requirement, a valid ASE configuration will satify:
-// - matched with any sink capability (if presented)
-// - OR matched with any source capability (if presented)
+// - matched with the sink capability (if presented)
+// - AND matched with the source capability (if presented)
 // - and the setting need to pass the requirement
 ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseConfiguration(
     const std::optional<std::vector<
@@ -714,101 +821,92 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
 
-  // Split out preferred and non-preferred settings based on context
-  // An example: preferred = MEDIA, available: MEDIA | CONVERSATION
-  // -> preferred list will have settings with MEDIA context
-  // -> non-preferred list will have settings with any context
-  // We want to match requirement with preferred context settings first
+  // Matched ASE configuration with ignored audio context
+  std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+      sink_matched_ase_configuration_settings;
   std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
       matched_ase_configuration_settings;
-  // Matched ASE configuration with non-preferred audio context
-  std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
-      non_prefer_matched_ase_configuration_settings;
 
-  if (in_remoteSinkAudioCapabilities.has_value())
-    // Matching each setting with any remote capabilities
-    for (auto& setting : ase_configuration_settings)
+  // A setting must match both source and sink.
+  // First filter all setting matched with sink capability
+  if (in_remoteSinkAudioCapabilities.has_value()) {
+    for (auto& setting : ase_configuration_settings) {
       for (auto& capability : in_remoteSinkAudioCapabilities.value()) {
         if (!capability.has_value()) continue;
         auto filtered_ase_configuration_setting =
             getCapabilitiesMatchedAseConfigurationSettings(
                 setting, capability.value(), kLeAudioDirectionSink);
         if (filtered_ase_configuration_setting.has_value()) {
-          // Push to non-prefer first for the broadest matching possible
-          non_prefer_matched_ase_configuration_settings.push_back(
+          sink_matched_ase_configuration_settings.push_back(
               filtered_ase_configuration_setting.value());
-          // Try to filter out prefer context to another vector.
-          if (filterCapabilitiesMatchedContext(
-                  filtered_ase_configuration_setting.value().audioContext,
-                  capability.value())) {
-            matched_ase_configuration_settings.push_back(
-                filtered_ase_configuration_setting.value());
-          }
         }
       }
+    }
+  } else {
+    sink_matched_ase_configuration_settings = ase_configuration_settings;
+  }
 
   // Combine filter every source capability
-  if (in_remoteSourceAudioCapabilities.has_value())
-    // Matching each setting with any remote capabilities
-    for (auto& setting : ase_configuration_settings)
+  if (in_remoteSourceAudioCapabilities.has_value()) {
+    for (auto& setting : sink_matched_ase_configuration_settings)
       for (auto& capability : in_remoteSourceAudioCapabilities.value()) {
         if (!capability.has_value()) continue;
         auto filtered_ase_configuration_setting =
             getCapabilitiesMatchedAseConfigurationSettings(
                 setting, capability.value(), kLeAudioDirectionSource);
         if (filtered_ase_configuration_setting.has_value()) {
-          // Put into the same list
-          // possibly duplicated, filtered by requirement later
-          // Push to non-prefer first for the broadest matching possible
-          non_prefer_matched_ase_configuration_settings.push_back(
+          matched_ase_configuration_settings.push_back(
               filtered_ase_configuration_setting.value());
-          // Try to filter out prefer context to another vector.
-          if (filterCapabilitiesMatchedContext(
-                  filtered_ase_configuration_setting.value().audioContext,
-                  capability.value())) {
-            matched_ase_configuration_settings.push_back(
-                filtered_ase_configuration_setting.value());
-          }
         }
       }
+  } else {
+    matched_ase_configuration_settings =
+        sink_matched_ase_configuration_settings;
+  }
 
-  // Matching priority list:
-  // Preferred context - exact match with allocation
-  // Any context - exact match with allocation
-  // Preferred context - loose match with allocation
-  // Any context - loose match with allocation
+  std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> result;
+  for (auto& requirement : in_requirements) {
+    // For each requirement, try to match with a setting.
+    // If we cannot match, return an empty result.
 
-  // A loose match will attempt to return 2 settings with the
-  // combined allocation bitmask equal the required allocation.
-  // For example, we can return 2 link (left link and right link) when
-  // the requirement required 1 (left + right) link.
-  auto result = matchWithRequirement(matched_ase_configuration_settings,
-                                     in_requirements, true);
-  if (result.empty()) {
-    LOG(WARNING)
-        << __func__
-        << ": Cannot match with preferred context settings - exact match";
-    result = matchWithRequirement(non_prefer_matched_ase_configuration_settings,
-                                  in_requirements, true);
+    // Matching priority list:
+    // Matched configuration flags, i.e. for asymmetric requirement.
+    // Preferred context - exact match with allocation
+    // Preferred context - loose match with allocation
+    // Any context - exact match with allocation
+    // Any context - loose match with allocation
+    bool found = false;
+    for (bool match_flag : {true, false}) {
+      for (bool match_context : {true, false}) {
+        for (bool match_exact : {true, false}) {
+          auto matched_setting = matchWithRequirement(
+              matched_ase_configuration_settings, requirement, match_context,
+              match_exact, match_flag);
+          if (matched_setting.has_value()) {
+            result.push_back(matched_setting.value());
+            found = true;
+            break;
+          }
+        }
+        if (found) break;
+      }
+      if (found) break;
+    }
+
+    if (!found) {
+      LOG(ERROR) << __func__
+                 << ": Cannot find any match for this requirement, exitting...";
+      result.clear();
+      *_aidl_return = result;
+      return ndk::ScopedAStatus::ok();
+    }
   }
-  if (result.empty()) {
-    LOG(WARNING)
-        << __func__
-        << ": Cannot match with non-preferred context settings - exact match";
-    result = matchWithRequirement(matched_ase_configuration_settings,
-                                  in_requirements, false);
+
+  LOG(INFO) << __func__
+            << ": Found matches for all requirements, chosen settings:";
+  for (auto& setting : result) {
+    LOG(INFO) << __func__ << ": " << getSettingOutputString(setting);
   }
-  if (result.empty()) {
-    LOG(WARNING) << __func__
-                 << ": Cannot match with preferred context settings - "
-                    "non-exact match";
-    result = matchWithRequirement(non_prefer_matched_ase_configuration_settings,
-                                  in_requirements, false);
-  }
-  if (result.empty())
-    LOG(ERROR) << __func__
-               << ": Cannot match with non preferred context settings - "
-                  "non-exact match";
   *_aidl_return = result;
   return ndk::ScopedAStatus::ok();
 };
@@ -840,7 +938,13 @@
     const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
         qosRequirement,
     std::vector<LeAudioAseConfigurationSetting>& ase_configuration_settings,
-    bool is_exact) {
+    bool isExact, bool isMatchFlags) {
+  auto requirement_flags_bitmask = 0;
+  if (isMatchFlags) {
+    if (!qosRequirement.flags.has_value()) return std::nullopt;
+    requirement_flags_bitmask = qosRequirement.flags.value().bitmask;
+  }
+
   std::optional<AseQosDirectionRequirement> direction_qos_requirement =
       std::nullopt;
 
@@ -856,9 +960,18 @@
     if ((setting.audioContext.bitmask & qosRequirement.audioContext.bitmask) !=
         qosRequirement.audioContext.bitmask)
       continue;
+    LOG(DEBUG) << __func__ << ": Setting with matched context: "
+               << getSettingOutputString(setting);
 
     // Match configuration flags
-    // Currently configuration flags are not populated, ignore.
+    if (isMatchFlags) {
+      if (!setting.flags.has_value()) continue;
+      if ((setting.flags.value().bitmask & requirement_flags_bitmask) !=
+          requirement_flags_bitmask)
+        continue;
+      LOG(DEBUG) << __func__ << ": Setting with matched flags: "
+                 << getSettingOutputString(setting);
+    }
 
     // Get a list of all matched AseDirectionConfiguration
     // for the input direction
@@ -907,7 +1020,7 @@
         direction_qos_requirement.value().aseConfiguration);
     // Get the best matching config based on channel allocation
     auto req_valid_configs = getValidConfigurationsFromAllocation(
-        qos_allocation_bitmask, temp, is_exact);
+        qos_allocation_bitmask, temp, isExact);
     if (req_valid_configs.empty()) {
       LOG(WARNING) << __func__
                    << ": Cannot find matching allocation for bitmask "
@@ -937,29 +1050,38 @@
   if (in_qosRequirement.sinkAseQosRequirement.has_value()) {
     if (!isValidQosRequirement(in_qosRequirement.sinkAseQosRequirement.value()))
       return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
-    {
-      // Try exact match first
-      result.sinkQosConfiguration =
-          getDirectionQosConfiguration(kLeAudioDirectionSink, in_qosRequirement,
-                                       ase_configuration_settings, true);
-      if (!result.sinkQosConfiguration.has_value()) {
-        result.sinkQosConfiguration = getDirectionQosConfiguration(
+    bool found = false;
+    for (bool match_flag : {true, false}) {
+      for (bool match_exact : {true, false}) {
+        auto setting = getDirectionQosConfiguration(
             kLeAudioDirectionSink, in_qosRequirement,
-            ase_configuration_settings, false);
+            ase_configuration_settings, match_exact, match_flag);
+        if (setting.has_value()) {
+          found = true;
+          result.sinkQosConfiguration = setting;
+          break;
+        }
       }
+      if (found) break;
     }
   }
   if (in_qosRequirement.sourceAseQosRequirement.has_value()) {
     if (!isValidQosRequirement(
             in_qosRequirement.sourceAseQosRequirement.value()))
       return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
-    result.sourceQosConfiguration =
-        getDirectionQosConfiguration(kLeAudioDirectionSource, in_qosRequirement,
-                                     ase_configuration_settings, true);
-    if (!result.sourceQosConfiguration.has_value()) {
-      result.sourceQosConfiguration = getDirectionQosConfiguration(
-          kLeAudioDirectionSource, in_qosRequirement,
-          ase_configuration_settings, false);
+    bool found = false;
+    for (bool match_flag : {true, false}) {
+      for (bool match_exact : {true, false}) {
+        auto setting = getDirectionQosConfiguration(
+            kLeAudioDirectionSource, in_qosRequirement,
+            ase_configuration_settings, match_exact, match_flag);
+        if (setting.has_value()) {
+          found = true;
+          result.sourceQosConfiguration = setting;
+          break;
+        }
+      }
+      if (found) break;
     }
   }
 
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
index 043d923..8c4f543 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
@@ -140,7 +140,7 @@
       const std::vector<std::optional<AseDirectionRequirement>>& requirements,
       std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
           valid_direction_configurations,
-      bool is_exact);
+      bool isExact);
   std::optional<LeAudioAseConfigurationSetting>
   getCapabilitiesMatchedAseConfigurationSettings(
       IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
@@ -151,7 +151,7 @@
       IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
       const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
           requirement,
-      bool is_exact);
+      bool isExact);
   bool isMatchedQosRequirement(LeAudioAseQosConfiguration setting_qos,
                                AseQosDirectionRequirement requirement_qos);
   std::optional<LeAudioBroadcastConfigurationSetting>
@@ -164,19 +164,18 @@
       const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
           qosRequirement,
       std::vector<LeAudioAseConfigurationSetting>& ase_configuration_settings,
-      bool is_exact);
+      bool isExact, bool isMatchedFlag);
   bool isSubgroupConfigurationMatchedContext(
       AudioContext requirement_context,
       IBluetoothAudioProvider::BroadcastQuality quality,
       LeAudioBroadcastSubgroupConfiguration configuration);
-  std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+  std::optional<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
   matchWithRequirement(
       std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>&
           matched_ase_configuration_settings,
-      const std::vector<
-          IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
-          in_requirements,
-      bool is_exact);
+      const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
+          requirements,
+      bool isMatchContext, bool isExact, bool isMatchFlags);
 };
 
 class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
diff --git a/bluetooth/audio/aidl/vts/Android.bp b/bluetooth/audio/aidl/vts/Android.bp
index 884062a..b0b095d 100644
--- a/bluetooth/audio/aidl/vts/Android.bp
+++ b/bluetooth/audio/aidl/vts/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_bluetooth",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
index 110a628..a52d761 100644
--- a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -142,6 +142,7 @@
   VERSION_AIDL_V2,
   VERSION_AIDL_V3,
   VERSION_AIDL_V4,
+  VERSION_AIDL_V5,
 };
 
 // Some valid configs for HFP PCM configuration (software sessions)
@@ -683,6 +684,8 @@
         return BluetoothAudioHalVersion::VERSION_AIDL_V3;
       case 4:
         return BluetoothAudioHalVersion::VERSION_AIDL_V4;
+      case 5:
+        return BluetoothAudioHalVersion::VERSION_AIDL_V5;
       default:
         return BluetoothAudioHalVersion::VERSION_UNAVAILABLE;
     }
@@ -2372,6 +2375,43 @@
     return capability;
   }
 
+  LeAudioDeviceCapabilities GetOpusRemoteSinkCapability() {
+    // Create a capability specifically for vendor OPUS
+    LeAudioDeviceCapabilities capability;
+
+    auto vendor_codec = CodecId::Vendor();
+    vendor_codec.codecId = 255;
+    vendor_codec.id = 224;
+    capability.codecId = vendor_codec;
+
+    auto pref_context_metadata = MetadataLtv::PreferredAudioContexts();
+    pref_context_metadata.values =
+        GetAudioContext(AudioContext::MEDIA | AudioContext::CONVERSATIONAL |
+                        AudioContext::GAME);
+    capability.metadata = {pref_context_metadata};
+
+    auto sampling_rate =
+        CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies();
+    sampling_rate.bitmask =
+        CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ16000 |
+        CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ8000 |
+        CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ48000;
+    auto frame_duration =
+        CodecSpecificCapabilitiesLtv::SupportedFrameDurations();
+    frame_duration.bitmask =
+        CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500 |
+        CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US10000 |
+        CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US20000;
+    auto octets = CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame();
+    octets.min = 0;
+    octets.max = 240;
+    auto frames = CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU();
+    frames.value = 2;
+    capability.codecSpecificCapabilities = {sampling_rate, frame_duration,
+                                            octets, frames};
+    return capability;
+  }
+
   LeAudioDeviceCapabilities GetDefaultRemoteSourceCapability() {
     // Create a capability
     LeAudioDeviceCapabilities capability;
@@ -2742,6 +2782,41 @@
     return requirement;
   }
 
+  LeAudioConfigurationRequirement GetOpusUnicastRequirement(
+      int32_t context_bits, bool is_sink_requirement,
+      bool is_source_requriement,
+      CodecSpecificConfigurationLtv::SamplingFrequency freq =
+          CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000) {
+    // Create a requirements
+    LeAudioConfigurationRequirement requirement;
+    requirement.audioContext = GetAudioContext(context_bits);
+
+    auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
+    allocation.bitmask =
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
+
+    auto direction_ase_requriement = AseDirectionRequirement();
+    auto vendor_codec = CodecId::Vendor();
+    vendor_codec.codecId = 255;
+    vendor_codec.id = 224;
+    direction_ase_requriement.aseConfiguration.codecId = vendor_codec;
+    direction_ase_requriement.aseConfiguration.targetLatency =
+        LeAudioAseConfiguration::TargetLatency::HIGHER_RELIABILITY;
+
+    direction_ase_requriement.aseConfiguration.codecConfiguration = {
+        freq, CodecSpecificConfigurationLtv::FrameDuration::US20000, allocation
+
+    };
+    if (is_sink_requirement)
+      requirement.sinkAseRequirement = {direction_ase_requriement};
+
+    if (is_source_requriement)
+      requirement.sourceAseRequirement = {direction_ase_requriement};
+
+    return requirement;
+  }
+
   LeAudioConfigurationRequirement GetUnicastGameRequirement(bool asymmetric) {
     // Create a requirements
     LeAudioConfigurationRequirement requirement;
@@ -3169,6 +3244,31 @@
 }
 
 TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+       GetOpusAseConfiguration) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+
+  std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
+      GetOpusRemoteSinkCapability()};
+  std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
+      GetDefaultRemoteSourceCapability()};
+
+  std::vector<LeAudioAseConfigurationSetting> configurations;
+  std::vector<LeAudioConfigurationRequirement> sink_requirements = {
+      GetOpusUnicastRequirement(AudioContext::MEDIA, true /* sink */,
+                                false /* source */)};
+  auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      sink_capabilities, std::nullopt, sink_requirements, &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  if (!configurations.empty()) {
+    VerifyIfRequirementsSatisfied(sink_requirements, configurations);
+  }
+}
+
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
        GetAseConfiguration_Multidirectional) {
   if (GetProviderFactoryInterfaceVersion() <
       BluetoothAudioHalVersion::VERSION_AIDL_V4) {
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 1661362..6d1da63 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -81,9 +81,9 @@
     ],
     required: [
         "aidl_audio_set_configurations_bfbs",
-        "aidl_audio_set_configurations_json",
+        "aidl_default_audio_set_configurations_json",
         "aidl_audio_set_scenarios_bfbs",
-        "aidl_audio_set_scenarios_json",
+        "aidl_default_audio_set_scenarios_json",
         "hfp_codec_capabilities_xml",
     ],
 }
@@ -91,7 +91,9 @@
 cc_test {
     name: "BluetoothLeAudioCodecsProviderTest",
     defaults: [
-        "latest_android_hardware_bluetooth_audio_ndk_shared",
+        "latest_android_hardware_audio_common_ndk_static",
+        "latest_android_hardware_bluetooth_audio_ndk_static",
+        "latest_android_media_audio_common_types_ndk_static",
     ],
     srcs: [
         "aidl_session/BluetoothLeAudioCodecsProvider.cpp",
@@ -215,9 +217,9 @@
 }
 
 prebuilt_etc {
-    name: "aidl_audio_set_scenarios_json",
+    name: "aidl_default_audio_set_scenarios_json",
     src: "le_audio_configuration_set/audio_set_scenarios.json",
-    filename: "aidl_audio_set_scenarios.json",
+    filename: "aidl_default_audio_set_scenarios.json",
     sub_dir: "aidl/le_audio",
     vendor: true,
 }
@@ -239,9 +241,9 @@
 }
 
 prebuilt_etc {
-    name: "aidl_audio_set_configurations_json",
+    name: "aidl_default_audio_set_configurations_json",
     src: "le_audio_configuration_set/audio_set_configurations.json",
-    filename: "aidl_audio_set_configurations.json",
+    filename: "aidl_default_audio_set_configurations.json",
     sub_dir: "aidl/le_audio",
     vendor: true,
 }
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index d0f2a26..c62784e 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -139,21 +139,50 @@
                   << toString(session_type_);
         return;
       }
+    } else if(session_type_ == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH) {
+      if (audio_config.getTag() != AudioConfiguration::hfpConfig) {
+        LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
+                  << toString(session_type_);
+        return;
+      }
+    } else if (session_type_ == SessionType::HFP_SOFTWARE_DECODING_DATAPATH ||
+               session_type_ == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH) {
+      if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+        LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
+                   << toString(session_type_);
+        return;
+      }
     } else {
       LOG(ERROR) << __func__ << " invalid SessionType ="
                  << toString(session_type_);
       return;
     }
   } else {
-    if (session_type_ !=
-            SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
-        session_type_ !=
+    if (session_type_ ==
+            SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+        session_type_ ==
             SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-      return;
-    }
-    if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
-      LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
-                 << toString(session_type_);
+      if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
+        LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
+                   << toString(session_type_);
+        return;
+      }
+    } else if(session_type_ == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH) {
+      if (audio_config.getTag() != AudioConfiguration::hfpConfig) {
+        LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
+                  << toString(session_type_);
+        return;
+      }
+    } else if (session_type_ == SessionType::HFP_SOFTWARE_DECODING_DATAPATH ||
+               session_type_ == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH) {
+      if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+        LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
+                   << toString(session_type_);
+        return;
+      }
+    } else {
+      LOG(ERROR) << __func__
+                 << " invalid SessionType =" << toString(session_type_);
       return;
     }
   }
@@ -589,7 +618,9 @@
   if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
       session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
       session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
-      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+      session_type_ == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH ||
+      session_type_ == SessionType::HFP_SOFTWARE_DECODING_DATAPATH) {
     return false;
   }
 
@@ -614,7 +645,9 @@
   if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
       session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
       session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
-      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+      session_type_ == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH ||
+      session_type_ == SessionType::HFP_SOFTWARE_DECODING_DATAPATH) {
     return false;
   }
 
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
index 780154a..3e18de2 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
@@ -47,6 +47,8 @@
 #include <aidl/android/hardware/bluetooth/audio/Phy.h>
 #include <android-base/logging.h>
 
+#include <optional>
+
 #include "flatbuffers/idl.h"
 #include "flatbuffers/util.h"
 
@@ -92,9 +94,10 @@
 /* Frame Durations */
 constexpr uint8_t kLeAudioCodecFrameDur7500us = 0x00;
 constexpr uint8_t kLeAudioCodecFrameDur10000us = 0x01;
+constexpr uint8_t kLeAudioCodecFrameDur20000us = 0x02;
 
 /* Audio Allocations */
-constexpr uint32_t kLeAudioLocationNotAllowed = 0x00000000;
+constexpr uint32_t kLeAudioLocationMonoAudio = 0x00000000;
 constexpr uint32_t kLeAudioLocationFrontLeft = 0x00000001;
 constexpr uint32_t kLeAudioLocationFrontRight = 0x00000002;
 constexpr uint32_t kLeAudioLocationFrontCenter = 0x00000004;
@@ -171,12 +174,14 @@
         {kLeAudioCodecFrameDur7500us,
          CodecSpecificConfigurationLtv::FrameDuration::US7500},
         {kLeAudioCodecFrameDur10000us,
-         CodecSpecificConfigurationLtv::FrameDuration::US10000}};
+         CodecSpecificConfigurationLtv::FrameDuration::US10000},
+        {kLeAudioCodecFrameDur20000us,
+         CodecSpecificConfigurationLtv::FrameDuration::US20000}};
 
 /* Helper map for matching various audio channel allocation notations */
 std::map<uint32_t, uint32_t> audio_channel_allocation_map = {
-    {kLeAudioLocationNotAllowed,
-     CodecSpecificConfigurationLtv::AudioChannelAllocation::NOT_ALLOWED},
+    {kLeAudioLocationMonoAudio,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::MONO},
     {kLeAudioLocationFrontLeft,
      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT},
     {kLeAudioLocationFrontRight,
@@ -240,18 +245,31 @@
      CodecSpecificConfigurationLtv::AudioChannelAllocation::RIGHT_SURROUND},
 };
 
+// Set configuration and scenario files with fallback default
 static const std::vector<
     std::pair<const char* /*schema*/, const char* /*content*/>>
-    kLeAudioSetConfigs = {{"/vendor/etc/aidl/le_audio/"
-                           "aidl_audio_set_configurations.bfbs",
-                           "/vendor/etc/aidl/le_audio/"
-                           "aidl_audio_set_configurations.json"}};
+    kLeAudioSetConfigs = {
+        {"/vendor/etc/aidl/le_audio/"
+         "aidl_audio_set_configurations.bfbs",
+         "/vendor/etc/aidl/le_audio/"
+         "aidl_audio_set_configurations.json"},
+
+        {"/vendor/etc/aidl/le_audio/"
+         "aidl_audio_set_configurations.bfbs",
+         "/vendor/etc/aidl/le_audio/"
+         "aidl_default_audio_set_configurations.json"},
+};
 static const std::vector<
     std::pair<const char* /*schema*/, const char* /*content*/>>
     kLeAudioSetScenarios = {{"/vendor/etc/aidl/le_audio/"
                              "aidl_audio_set_scenarios.bfbs",
                              "/vendor/etc/aidl/le_audio/"
-                             "aidl_audio_set_scenarios.json"}};
+                             "aidl_audio_set_scenarios.json"},
+
+                            {"/vendor/etc/aidl/le_audio/"
+                             "aidl_audio_set_scenarios.bfbs",
+                             "/vendor/etc/aidl/le_audio/"
+                             "aidl_default_audio_set_scenarios.json"}};
 
 /* Implementation */
 
@@ -374,7 +392,7 @@
 }
 
 void AudioSetConfigurationProviderJson::populateAseConfiguration(
-    LeAudioAseConfiguration& ase,
+    const std::string& name, LeAudioAseConfiguration& ase,
     const le_audio::AudioSetSubConfiguration* flat_subconfig,
     const le_audio::QosConfiguration* qos_cfg) {
   // Target latency
@@ -411,20 +429,36 @@
   }
   // Codec configuration data
   populateConfigurationData(ase, flat_subconfig->codec_configuration());
+  // Populate the config name for easier debug
+  auto meta = std::vector<std::optional<MetadataLtv>>();
+  MetadataLtv::VendorSpecific cfg_name;
+  cfg_name.opaqueValue = std::vector<uint8_t>(name.begin(), name.end());
+  meta.push_back(cfg_name);
+  ase.metadata = meta;
 }
 
 void AudioSetConfigurationProviderJson::populateAseQosConfiguration(
     LeAudioAseQosConfiguration& qos, const le_audio::QosConfiguration* qos_cfg,
-    LeAudioAseConfiguration& ase) {
+    LeAudioAseConfiguration& ase, uint8_t ase_channel_cnt) {
   std::optional<CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU>
       frameBlock = std::nullopt;
   std::optional<CodecSpecificConfigurationLtv::FrameDuration> frameDuration =
       std::nullopt;
-  std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>
-      allocation = std::nullopt;
   std::optional<CodecSpecificConfigurationLtv::OctetsPerCodecFrame> octet =
       std::nullopt;
 
+  // Hack to put back allocation
+  CodecSpecificConfigurationLtv::AudioChannelAllocation allocation =
+      CodecSpecificConfigurationLtv::AudioChannelAllocation();
+  if (ase_channel_cnt == 1) {
+    allocation.bitmask |=
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER;
+
+  } else {
+    allocation.bitmask |=
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
+  }
   for (auto& cfg_ltv : ase.codecConfiguration) {
     auto tag = cfg_ltv.getTag();
     if (tag == CodecSpecificConfigurationLtv::codecFrameBlocksPerSDU) {
@@ -433,11 +467,12 @@
     } else if (tag == CodecSpecificConfigurationLtv::frameDuration) {
       frameDuration =
           cfg_ltv.get<CodecSpecificConfigurationLtv::frameDuration>();
-    } else if (tag == CodecSpecificConfigurationLtv::audioChannelAllocation) {
-      allocation =
-          cfg_ltv.get<CodecSpecificConfigurationLtv::audioChannelAllocation>();
     } else if (tag == CodecSpecificConfigurationLtv::octetsPerCodecFrame) {
       octet = cfg_ltv.get<CodecSpecificConfigurationLtv::octetsPerCodecFrame>();
+    } else if (tag == CodecSpecificConfigurationLtv::audioChannelAllocation) {
+      // Change to the old hack allocation
+      cfg_ltv.set<CodecSpecificConfigurationLtv::audioChannelAllocation>(
+          allocation);
     }
   }
 
@@ -445,9 +480,8 @@
   if (frameBlock.has_value()) frameBlockValue = frameBlock.value().value;
 
   // Populate maxSdu
-  if (allocation.has_value() && octet.has_value()) {
-    auto channel_count = std::bitset<32>(allocation.value().bitmask).count();
-    qos.maxSdu = channel_count * octet.value().value * frameBlockValue;
+  if (octet.has_value()) {
+    qos.maxSdu = ase_channel_cnt * octet.value().value * frameBlockValue;
   }
   // Populate sduIntervalUs
   if (frameDuration.has_value()) {
@@ -458,6 +492,9 @@
       case CodecSpecificConfigurationLtv::FrameDuration::US10000:
         qos.sduIntervalUs = 10000;
         break;
+      case CodecSpecificConfigurationLtv::FrameDuration::US20000:
+        qos.sduIntervalUs = 20000;
+        break;
     }
     qos.sduIntervalUs *= frameBlockValue;
   }
@@ -468,6 +505,7 @@
 // Parse into AseDirectionConfiguration
 AseDirectionConfiguration
 AudioSetConfigurationProviderJson::SetConfigurationFromFlatSubconfig(
+    const std::string& name,
     const le_audio::AudioSetSubConfiguration* flat_subconfig,
     const le_audio::QosConfiguration* qos_cfg, CodecLocation location) {
   AseDirectionConfiguration direction_conf;
@@ -477,10 +515,11 @@
   LeAudioDataPathConfiguration path;
 
   // Translate into LeAudioAseConfiguration
-  populateAseConfiguration(ase, flat_subconfig, qos_cfg);
+  populateAseConfiguration(name, ase, flat_subconfig, qos_cfg);
 
   // Translate into LeAudioAseQosConfiguration
-  populateAseQosConfiguration(qos, qos_cfg, ase);
+  populateAseQosConfiguration(qos, qos_cfg, ase,
+                              flat_subconfig->ase_channel_cnt());
 
   // Translate location to data path id
   switch (location) {
@@ -510,13 +549,29 @@
 // Parse into AseDirectionConfiguration and the ConfigurationFlags
 // and put them in the given list.
 void AudioSetConfigurationProviderJson::processSubconfig(
+    const std::string& name,
     const le_audio::AudioSetSubConfiguration* subconfig,
     const le_audio::QosConfiguration* qos_cfg,
     std::vector<std::optional<AseDirectionConfiguration>>&
         directionAseConfiguration,
     CodecLocation location) {
-  directionAseConfiguration.push_back(
-      SetConfigurationFromFlatSubconfig(subconfig, qos_cfg, location));
+  auto ase_cnt = subconfig->ase_cnt();
+  auto config =
+      SetConfigurationFromFlatSubconfig(name, subconfig, qos_cfg, location);
+  directionAseConfiguration.push_back(config);
+  // Put the same setting again.
+  if (ase_cnt == 2) directionAseConfiguration.push_back(config);
+}
+
+// Comparing if 2 AseDirectionConfiguration is equal.
+// Configuration are copied in, so we can remove some fields for comparison
+// without affecting the result.
+bool isAseConfigurationEqual(AseDirectionConfiguration cfg_a,
+                             AseDirectionConfiguration cfg_b) {
+  // Remove unneeded fields when comparing.
+  cfg_a.aseConfiguration.metadata = std::nullopt;
+  cfg_b.aseConfiguration.metadata = std::nullopt;
+  return cfg_a == cfg_b;
 }
 
 void AudioSetConfigurationProviderJson::PopulateAseConfigurationFromFlat(
@@ -527,7 +582,7 @@
     std::vector<std::optional<AseDirectionConfiguration>>&
         sourceAseConfiguration,
     std::vector<std::optional<AseDirectionConfiguration>>& sinkAseConfiguration,
-    ConfigurationFlags& /*configurationFlags*/) {
+    ConfigurationFlags& configurationFlags) {
   if (flat_cfg == nullptr) {
     LOG(ERROR) << "flat_cfg cannot be null";
     return;
@@ -587,11 +642,37 @@
     /* Load subconfigurations */
     for (auto subconfig : *codec_cfg->subconfigurations()) {
       if (subconfig->direction() == kLeAudioDirectionSink) {
-        processSubconfig(subconfig, qos_sink_cfg, sinkAseConfiguration,
-                         location);
+        processSubconfig(flat_cfg->name()->str(), subconfig, qos_sink_cfg,
+                         sinkAseConfiguration, location);
       } else {
-        processSubconfig(subconfig, qos_source_cfg, sourceAseConfiguration,
-                         location);
+        processSubconfig(flat_cfg->name()->str(), subconfig, qos_source_cfg,
+                         sourceAseConfiguration, location);
+      }
+    }
+
+    // After putting all subconfig, check if it's an asymmetric configuration
+    // and populate information for ConfigurationFlags
+    if (!sinkAseConfiguration.empty() && !sourceAseConfiguration.empty()) {
+      if (sinkAseConfiguration.size() == sourceAseConfiguration.size()) {
+        for (int i = 0; i < sinkAseConfiguration.size(); ++i) {
+          if (sinkAseConfiguration[i].has_value() !=
+              sourceAseConfiguration[i].has_value()) {
+            // Different configuration: one is not empty and other is.
+            configurationFlags.bitmask |=
+                ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS;
+          } else if (sinkAseConfiguration[i].has_value()) {
+            // Both is not empty, comparing inner fields:
+            if (!isAseConfigurationEqual(sinkAseConfiguration[i].value(),
+                                         sourceAseConfiguration[i].value())) {
+              configurationFlags.bitmask |=
+                  ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS;
+            }
+          }
+        }
+      } else {
+        // Different number of ASE, is a different configuration.
+        configurationFlags.bitmask |=
+            ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS;
       }
     }
   } else {
@@ -603,8 +684,6 @@
                  << "' has no valid subconfigurations.";
     }
   }
-
-  // TODO: Populate information for ConfigurationFlags
 }
 
 bool AudioSetConfigurationProviderJson::LoadConfigurationsFromFiles(
@@ -742,9 +821,6 @@
 
   LOG(DEBUG) << "Updating " << flat_scenarios->size() << " scenarios.";
   for (auto const& scenario : *flat_scenarios) {
-    LOG(DEBUG) << "Scenario " << scenario->name()->c_str()
-               << " configs: " << scenario->configurations()->size();
-
     if (!scenario->configurations()) continue;
     std::string scenario_name = scenario->name()->c_str();
     AudioContext context;
@@ -758,6 +834,9 @@
       context = AudioContext(game_context);
     else if (scenario_name == "VoiceAssistants")
       context = AudioContext(voice_assistants_context);
+    LOG(DEBUG) << "Scenario " << scenario->name()->c_str()
+               << " configs: " << scenario->configurations()->size()
+               << " context: " << context.toString();
 
     for (auto it = scenario->configurations()->begin();
          it != scenario->configurations()->end(); ++it) {
@@ -790,14 +869,22 @@
     std::vector<std::pair<const char* /*schema*/, const char* /*content*/>>
         scenario_files,
     CodecLocation location) {
+  bool is_loaded_config = false;
   for (auto [schema, content] : config_files) {
-    if (!LoadConfigurationsFromFiles(schema, content, location)) return false;
+    if (LoadConfigurationsFromFiles(schema, content, location)) {
+      is_loaded_config = true;
+      break;
+    }
   }
 
+  bool is_loaded_scenario = false;
   for (auto [schema, content] : scenario_files) {
-    if (!LoadScenariosFromFiles(schema, content)) return false;
+    if (LoadScenariosFromFiles(schema, content)) {
+      is_loaded_scenario = true;
+      break;
+    }
   }
-  return true;
+  return is_loaded_config && is_loaded_scenario;
 }
 
 }  // namespace audio
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
index 6639009..fac6152 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
@@ -73,19 +73,22 @@
           flat_codec_specific_params);
 
   static void populateAseConfiguration(
-      LeAudioAseConfiguration& ase,
+      const std::string& name, LeAudioAseConfiguration& ase,
       const le_audio::AudioSetSubConfiguration* flat_subconfig,
       const le_audio::QosConfiguration* qos_cfg);
 
   static void populateAseQosConfiguration(
       LeAudioAseQosConfiguration& qos,
-      const le_audio::QosConfiguration* qos_cfg, LeAudioAseConfiguration& ase);
+      const le_audio::QosConfiguration* qos_cfg, LeAudioAseConfiguration& ase,
+      uint8_t ase_channel_cnt);
 
   static AseDirectionConfiguration SetConfigurationFromFlatSubconfig(
+      const std::string& name,
       const le_audio::AudioSetSubConfiguration* flat_subconfig,
       const le_audio::QosConfiguration* qos_cfg, CodecLocation location);
 
   static void processSubconfig(
+      const std::string& name,
       const le_audio::AudioSetSubConfiguration* subconfig,
       const le_audio::QosConfiguration* qos_cfg,
       std::vector<std::optional<AseDirectionConfiguration>>&
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
index 473777c..a96df52 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
+#include <optional>
 #include <set>
 
 #include "aidl/android/hardware/bluetooth/audio/ChannelMode.h"
 #include "aidl/android/hardware/bluetooth/audio/CodecId.h"
+#include "aidl/android/hardware/bluetooth/audio/CodecInfo.h"
+#include "aidl/android/hardware/bluetooth/audio/ConfigurationFlags.h"
 #include "aidl_android_hardware_bluetooth_audio_setting_enums.h"
 #define LOG_TAG "BTAudioCodecsProviderAidl"
 
@@ -52,6 +55,26 @@
   return le_audio_offload_setting;
 }
 
+void add_flag(CodecInfo& codec_info, int32_t bitmask) {
+  auto& transport =
+      codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
+  if (!transport.flags.has_value()) transport.flags = ConfigurationFlags();
+  transport.flags->bitmask |= bitmask;
+}
+
+// Compare 2 codec info to see if they are equal.
+// Currently only compare bitdepth, frameDurationUs and samplingFrequencyHz
+bool is_equal(CodecInfo& codec_info_a, CodecInfo& codec_info_b) {
+  auto& transport_a =
+      codec_info_a.transport.get<CodecInfo::Transport::Tag::leAudio>();
+  auto& transport_b =
+      codec_info_b.transport.get<CodecInfo::Transport::Tag::leAudio>();
+  return codec_info_a.name == codec_info_b.name &&
+         transport_a.bitdepth == transport_b.bitdepth &&
+         transport_a.frameDurationUs == transport_b.frameDurationUs &&
+         transport_a.samplingFrequencyHz == transport_b.samplingFrequencyHz;
+}
+
 std::unordered_map<SessionType, std::vector<CodecInfo>>
 BluetoothLeAudioCodecsProvider::GetLeAudioCodecInfo(
     const std::optional<setting::LeAudioOffloadSetting>&
@@ -111,6 +134,9 @@
     codec_info.transport =
         CodecInfo::Transport::make<CodecInfo::Transport::Tag::leAudio>();
 
+    // Add low latency support by default
+    add_flag(codec_info, ConfigurationFlags::LOW_LATENCY);
+
     // Mapping codec configuration information
     auto& transport =
         codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
@@ -119,19 +145,55 @@
     // Mapping octetsPerCodecFrame to bitdepth for easier comparison.
     transport.bitdepth.push_back(codec_config.getOctetsPerCodecFrame());
     transport.frameDurationUs.push_back(codec_config.getFrameDurationUs());
-    switch (strategy_config.getAudioLocation()) {
-      case setting::AudioLocation::MONO:
+    if (strategy_config.hasAudioLocation()) {
+      switch (strategy_config.getAudioLocation()) {
+        case setting::AudioLocation::MONO:
+          if (strategy_config_channel_count == 1)
+            transport.channelMode.push_back(ChannelMode::MONO);
+          else
+            transport.channelMode.push_back(ChannelMode::DUALMONO);
+          break;
+        case setting::AudioLocation::STEREO:
+          transport.channelMode.push_back(ChannelMode::STEREO);
+          break;
+        default:
+          transport.channelMode.push_back(ChannelMode::UNKNOWN);
+          break;
+      }
+    } else if (strategy_config.hasAudioChannelAllocation()) {
+      auto count =
+          std::bitset<32>(strategy_config.getAudioChannelAllocation()).count();
+      if (count <= 1) {
         if (strategy_config_channel_count == 1)
           transport.channelMode.push_back(ChannelMode::MONO);
         else
           transport.channelMode.push_back(ChannelMode::DUALMONO);
-        break;
-      case setting::AudioLocation::STEREO:
+      } else if (count == 2) {
         transport.channelMode.push_back(ChannelMode::STEREO);
-        break;
-      default:
+      } else {
         transport.channelMode.push_back(ChannelMode::UNKNOWN);
-        break;
+      }
+    } else {
+      transport.channelMode.push_back(ChannelMode::UNKNOWN);
+    }
+  }
+
+  // Goes through a list of scenarios and detect asymmetrical config using
+  // codecConfiguration name.
+  for (auto& s : supported_scenarios_) {
+    if (s.hasEncode() && s.hasDecode() &&
+        config_codec_info_map_.count(s.getEncode()) &&
+        config_codec_info_map_.count(s.getDecode())) {
+      // Check if it's actually using the different codec
+      auto& encode_codec_info = config_codec_info_map_[s.getEncode()];
+      auto& decode_codec_info = config_codec_info_map_[s.getDecode()];
+      if (!is_equal(encode_codec_info, decode_codec_info)) {
+        // Change both x and y to become asymmetrical
+        add_flag(encode_codec_info,
+                 ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS);
+        add_flag(decode_codec_info,
+                 ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS);
+      }
     }
   }
 
@@ -336,8 +398,12 @@
   for (const auto& scenario : supported_scenarios) {
     UnicastCapability unicast_encode_capability =
         GetUnicastCapability(scenario.getEncode());
+    LOG(INFO) << __func__ << ": Unicast capability encode = "
+              << unicast_encode_capability.toString();
     UnicastCapability unicast_decode_capability =
         GetUnicastCapability(scenario.getDecode());
+    LOG(INFO) << __func__ << ": Unicast capability decode = "
+              << unicast_decode_capability.toString();
     BroadcastCapability broadcast_capability = {.codecType =
                                                     CodecType::UNKNOWN};
 
@@ -384,22 +450,36 @@
     return {.codecType = CodecType::UNKNOWN};
   }
 
+  // Populate audio location
+  AudioLocation audio_location = AudioLocation::UNKNOWN;
+  if (strategy_configuration_iter->second.hasAudioLocation()) {
+    audio_location = GetAudioLocation(
+        strategy_configuration_iter->second.getAudioLocation());
+  }
+
+  // Populate audio channel allocation
+  std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>
+      audio_channel_allocation = std::nullopt;
+  if (strategy_configuration_iter->second.hasAudioChannelAllocation()) {
+    LOG(INFO) << __func__ << ": has allocation";
+    CodecSpecificConfigurationLtv::AudioChannelAllocation tmp;
+    tmp.bitmask =
+        strategy_configuration_iter->second.getAudioChannelAllocation();
+    audio_channel_allocation = tmp;
+  }
+
   CodecType codec_type =
       GetCodecType(codec_configuration_iter->second.getCodec());
   if (codec_type == CodecType::LC3) {
     return ComposeUnicastCapability(
-        codec_type,
-        GetAudioLocation(
-            strategy_configuration_iter->second.getAudioLocation()),
+        codec_type, audio_location, audio_channel_allocation,
         strategy_configuration_iter->second.getConnectedDevice(),
         strategy_configuration_iter->second.getChannelCount(),
         ComposeLc3Capability(codec_configuration_iter->second));
   } else if (codec_type == CodecType::APTX_ADAPTIVE_LE ||
              codec_type == CodecType::APTX_ADAPTIVE_LEX) {
     return ComposeUnicastCapability(
-        codec_type,
-        GetAudioLocation(
-            strategy_configuration_iter->second.getAudioLocation()),
+        codec_type, audio_location, audio_channel_allocation,
         strategy_configuration_iter->second.getConnectedDevice(),
         strategy_configuration_iter->second.getChannelCount(),
         ComposeAptxAdaptiveLeCapability(codec_configuration_iter->second));
@@ -435,11 +515,27 @@
   std::vector<std::optional<Lc3Capabilities>> bcastLc3Cap(
       1, std::optional(ComposeLc3Capability(codec_configuration_iter->second)));
 
+  // Populate audio location
+  AudioLocation audio_location = AudioLocation::UNKNOWN;
+  if (strategy_configuration_iter->second.hasAudioLocation()) {
+    audio_location = GetAudioLocation(
+        strategy_configuration_iter->second.getAudioLocation());
+  }
+
+  // Populate audio channel allocation
+  std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>
+      audio_channel_allocation = std::nullopt;
+  if (strategy_configuration_iter->second.hasAudioChannelAllocation()) {
+    LOG(INFO) << __func__ << ": has allocation";
+    CodecSpecificConfigurationLtv::AudioChannelAllocation tmp;
+    tmp.bitmask =
+        strategy_configuration_iter->second.getAudioChannelAllocation();
+    audio_channel_allocation = tmp;
+  }
+
   if (codec_type == CodecType::LC3) {
     return ComposeBroadcastCapability(
-        codec_type,
-        GetAudioLocation(
-            strategy_configuration_iter->second.getAudioLocation()),
+        codec_type, audio_location, audio_channel_allocation,
         strategy_configuration_iter->second.getChannelCount(), bcastLc3Cap);
   }
   return {.codecType = CodecType::UNKNOWN};
@@ -448,16 +544,21 @@
 template <class T>
 BroadcastCapability BluetoothLeAudioCodecsProvider::ComposeBroadcastCapability(
     const CodecType& codec_type, const AudioLocation& audio_location,
+    const std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>&
+        audio_channel_allocation,
     const uint8_t& channel_count, const std::vector<T>& capability) {
   return {.codecType = codec_type,
           .supportedChannel = audio_location,
           .channelCountPerStream = channel_count,
-          .leAudioCodecCapabilities = std::optional(capability)};
+          .leAudioCodecCapabilities = std::optional(capability),
+          .audioLocation = audio_channel_allocation};
 }
 
 template <class T>
 UnicastCapability BluetoothLeAudioCodecsProvider::ComposeUnicastCapability(
     const CodecType& codec_type, const AudioLocation& audio_location,
+    const std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>&
+        audio_channel_allocation,
     const uint8_t& device_cnt, const uint8_t& channel_count,
     const T& capability) {
   return {
@@ -467,6 +568,7 @@
       .channelCountPerDevice = channel_count,
       .leAudioCodecCapabilities =
           UnicastCapability::LeAudioCodecCapabilities(capability),
+      .audioLocation = audio_channel_allocation,
   };
 }
 
@@ -519,38 +621,87 @@
          codec_configuration.hasOctetsPerCodecFrame();
 }
 
+bool IsValidStereoAudioLocation(
+    const setting::StrategyConfiguration& strategy_configuration) {
+  if ((strategy_configuration.getConnectedDevice() == 2 &&
+       strategy_configuration.getChannelCount() == 1) ||
+      (strategy_configuration.getConnectedDevice() == 1 &&
+       strategy_configuration.getChannelCount() == 2)) {
+    // Stereo
+    // 1. two connected device, one for L one for R
+    // 2. one connected device for both L and R
+    return true;
+  } else if (strategy_configuration.getConnectedDevice() == 0 &&
+             strategy_configuration.getChannelCount() == 2) {
+    // Broadcast
+    return true;
+  }
+  return false;
+}
+
+bool IsValidMonoAudioLocation(
+    const setting::StrategyConfiguration& strategy_configuration) {
+  if (strategy_configuration.getConnectedDevice() == 1 &&
+      strategy_configuration.getChannelCount() == 1) {
+    return true;
+  }
+  return false;
+}
+
+bool IsValidAudioLocation(
+    const setting::StrategyConfiguration& strategy_configuration) {
+  if (strategy_configuration.getAudioLocation() ==
+      setting::AudioLocation::STEREO)
+    return IsValidStereoAudioLocation(strategy_configuration);
+  else if (strategy_configuration.getAudioLocation() ==
+           setting::AudioLocation::MONO)
+    return IsValidMonoAudioLocation(strategy_configuration);
+  return false;
+}
+
+bool IsValidAudioChannelAllocation(
+    const setting::StrategyConfiguration& strategy_configuration) {
+  // First, ensure that there's only 2 bitmask enabled
+  int audio_channel_allocation =
+      strategy_configuration.getAudioChannelAllocation();
+  int count = 0;
+  for (int bit = 0; bit < 32; ++bit)
+    if (audio_channel_allocation & (1 << bit)) ++count;
+  if (count > 2) {
+    LOG(WARNING) << "Cannot parse more than 2 audio location, input is "
+                 << audio_channel_allocation;
+    return false;
+  }
+
+  if (count == 2)
+    return IsValidStereoAudioLocation(strategy_configuration);
+  else
+    return IsValidMonoAudioLocation(strategy_configuration);
+}
+
 bool BluetoothLeAudioCodecsProvider::IsValidStrategyConfiguration(
     const setting::StrategyConfiguration& strategy_configuration) {
   if (!strategy_configuration.hasName() ||
-      !strategy_configuration.hasAudioLocation() ||
       !strategy_configuration.hasConnectedDevice() ||
       !strategy_configuration.hasChannelCount()) {
     return false;
   }
-  if (strategy_configuration.getAudioLocation() ==
-      setting::AudioLocation::STEREO) {
-    if ((strategy_configuration.getConnectedDevice() == 2 &&
-         strategy_configuration.getChannelCount() == 1) ||
-        (strategy_configuration.getConnectedDevice() == 1 &&
-         strategy_configuration.getChannelCount() == 2)) {
-      // Stereo
-      // 1. two connected device, one for L one for R
-      // 2. one connected device for both L and R
-      return true;
-    } else if (strategy_configuration.getConnectedDevice() == 0 &&
-               strategy_configuration.getChannelCount() == 2) {
-      // Broadcast
-      return true;
-    }
-  } else if (strategy_configuration.getAudioLocation() ==
-             setting::AudioLocation::MONO) {
-    if (strategy_configuration.getConnectedDevice() == 1 &&
-        strategy_configuration.getChannelCount() == 1) {
-      // Mono
-      return true;
-    }
-  }
-  return false;
+
+  // Both audio location field cannot be empty
+  if (!strategy_configuration.hasAudioLocation() &&
+      !strategy_configuration.hasAudioChannelAllocation())
+    return false;
+
+  // Any audio location field that presents must be valid
+  if (strategy_configuration.hasAudioLocation() &&
+      !IsValidAudioLocation(strategy_configuration))
+    return false;
+
+  if (strategy_configuration.hasAudioChannelAllocation() &&
+      !IsValidAudioChannelAllocation(strategy_configuration))
+    return false;
+
+  return true;
 }
 
 }  // namespace audio
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
index 5bf67e2..23b2bb6 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
@@ -23,6 +23,7 @@
 #include <vector>
 
 #include "aidl/android/hardware/bluetooth/audio/CodecInfo.h"
+#include "aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.h"
 #include "aidl/android/hardware/bluetooth/audio/SessionType.h"
 #include "aidl_android_hardware_bluetooth_audio_setting.h"
 
@@ -84,12 +85,18 @@
   template <class T>
   static inline UnicastCapability ComposeUnicastCapability(
       const CodecType& codec_type, const AudioLocation& audio_location,
+      const std::optional<
+          CodecSpecificConfigurationLtv::AudioChannelAllocation>&
+          audio_channel_allocation,
       const uint8_t& device_cnt, const uint8_t& channel_count,
       const T& capability);
 
   template <class T>
   static inline BroadcastCapability ComposeBroadcastCapability(
       const CodecType& codec_type, const AudioLocation& audio_location,
+      const std::optional<
+          CodecSpecificConfigurationLtv::AudioChannelAllocation>&
+          audio_channel_allocation,
       const uint8_t& channel_count, const std::vector<T>& capability);
 
   static inline Lc3Capabilities ComposeLc3Capability(
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
index dba2749..6338e11 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
@@ -20,10 +20,16 @@
 #include <tuple>
 
 #include "BluetoothLeAudioCodecsProvider.h"
+#include "aidl/android/hardware/bluetooth/audio/CodecInfo.h"
+#include "aidl/android/hardware/bluetooth/audio/ConfigurationFlags.h"
+#include "aidl/android/hardware/bluetooth/audio/SessionType.h"
 
 using aidl::android::hardware::bluetooth::audio::BluetoothLeAudioCodecsProvider;
+using aidl::android::hardware::bluetooth::audio::CodecInfo;
+using aidl::android::hardware::bluetooth::audio::ConfigurationFlags;
 using aidl::android::hardware::bluetooth::audio::
     LeAudioCodecCapabilitiesSetting;
+using aidl::android::hardware::bluetooth::audio::SessionType;
 using aidl::android::hardware::bluetooth::audio::setting::AudioLocation;
 using aidl::android::hardware::bluetooth::audio::setting::CodecConfiguration;
 using aidl::android::hardware::bluetooth::audio::setting::
@@ -51,32 +57,129 @@
 static const Scenario kValidBroadcastScenario(
     std::nullopt, std::nullopt, std::make_optional("BcastStereo_16_2"));
 
+static const Scenario kValidAsymmetricScenario(
+    std::make_optional("OneChanStereo_32_1"),
+    std::make_optional("OneChanStereo_16_1"), std::nullopt);
+
 // Configuration
 static const Configuration kValidConfigOneChanStereo_16_1(
     std::make_optional("OneChanStereo_16_1"), std::make_optional("LC3_16k_1"),
     std::make_optional("STEREO_ONE_CIS_PER_DEVICE"));
+
+static const Configuration kValidConfigOneChanStereo_32_1(
+    std::make_optional("OneChanStereo_32_1"), std::make_optional("LC3_32k_1"),
+    std::make_optional("STEREO_ONE_CIS_PER_DEVICE"));
+
 // CodecConfiguration
 static const CodecConfiguration kValidCodecLC3_16k_1(
     std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3),
     std::nullopt, std::make_optional(16000), std::make_optional(7500),
     std::make_optional(30), std::nullopt);
+
+static const CodecConfiguration kValidCodecLC3_32k_1(
+    std::make_optional("LC3_32k_1"), std::make_optional(CodecType::LC3),
+    std::nullopt, std::make_optional(32000), std::make_optional(7500),
+    std::make_optional(30), std::nullopt);
+
 // StrategyConfiguration
 static const StrategyConfiguration kValidStrategyStereoOneCis(
     std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
     std::make_optional(AudioLocation::STEREO), std::make_optional(2),
-    std::make_optional(1));
+    std::make_optional(1), std::nullopt);
 static const StrategyConfiguration kValidStrategyStereoTwoCis(
     std::make_optional("STEREO_TWO_CISES_PER_DEVICE"),
     std::make_optional(AudioLocation::STEREO), std::make_optional(1),
-    std::make_optional(2));
+    std::make_optional(2), std::nullopt);
 static const StrategyConfiguration kValidStrategyMonoOneCis(
     std::make_optional("MONO_ONE_CIS_PER_DEVICE"),
     std::make_optional(AudioLocation::MONO), std::make_optional(1),
-    std::make_optional(1));
+    std::make_optional(1), std::nullopt);
 static const StrategyConfiguration kValidStrategyBroadcastStereo(
     std::make_optional("BROADCAST_STEREO"),
     std::make_optional(AudioLocation::STEREO), std::make_optional(0),
-    std::make_optional(2));
+    std::make_optional(2), std::nullopt);
+
+static const StrategyConfiguration kValidStrategyStereoOneCisInt(
+    std::make_optional("STEREO_ONE_CIS_PER_DEVICE"), std::nullopt,
+    std::make_optional(2), std::make_optional(1), std::make_optional(3));
+static const StrategyConfiguration kValidStrategyStereoTwoCisInt(
+    std::make_optional("STEREO_TWO_CISES_PER_DEVICE"), std::nullopt,
+    std::make_optional(1), std::make_optional(2), std::make_optional(3));
+static const StrategyConfiguration kValidStrategyMonoOneCisInt(
+    std::make_optional("MONO_ONE_CIS_PER_DEVICE"), std::nullopt,
+    std::make_optional(1), std::make_optional(1), std::make_optional(4));
+static const StrategyConfiguration kValidStrategyBroadcastStereoInt(
+    std::make_optional("BROADCAST_STEREO"), std::nullopt, std::make_optional(0),
+    std::make_optional(2), std::make_optional(3));
+
+static const StrategyConfiguration kValidStrategyStereoOneCisBoth(
+    std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
+    std::make_optional(AudioLocation::STEREO), std::make_optional(2),
+    std::make_optional(1), std::make_optional(3));
+static const StrategyConfiguration kValidStrategyStereoTwoCisBoth(
+    std::make_optional("STEREO_TWO_CISES_PER_DEVICE"),
+    std::make_optional(AudioLocation::STEREO), std::make_optional(1),
+    std::make_optional(2), std::make_optional(3));
+static const StrategyConfiguration kValidStrategyMonoOneCisBoth(
+    std::make_optional("MONO_ONE_CIS_PER_DEVICE"),
+    std::make_optional(AudioLocation::MONO), std::make_optional(1),
+    std::make_optional(1), std::make_optional(4));
+static const StrategyConfiguration kValidStrategyBroadcastStereoBoth(
+    std::make_optional("BROADCAST_STEREO"),
+    std::make_optional(AudioLocation::STEREO), std::make_optional(0),
+    std::make_optional(2), std::make_optional(3));
+
+// List of all invalid strategy configuration
+const auto kInvalidStrategyStereoTwoCisTwoDevice = StrategyConfigurationList(
+    std::vector<StrategyConfiguration>{StrategyConfiguration(
+        std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
+        std::make_optional(AudioLocation::STEREO), std::make_optional(2),
+        std::make_optional(2), std::nullopt)});
+const auto kInvalidStrategyMonoTwoCisTwoDevice = StrategyConfigurationList(
+    std::vector<StrategyConfiguration>{StrategyConfiguration(
+        std::make_optional("MONO_ONE_CIS_PER_DEVICE"),
+        std::make_optional(AudioLocation::STEREO), std::make_optional(2),
+        std::make_optional(2), std::nullopt)});
+const auto kInvalidStrategyNoName = StrategyConfigurationList(
+    std::vector<StrategyConfiguration>{StrategyConfiguration(
+        std::nullopt, std::make_optional(AudioLocation::STEREO),
+        std::make_optional(2), std::make_optional(1), std::nullopt)});
+const auto kInvalidStrategyNoLocation = StrategyConfigurationList(
+    std::vector<StrategyConfiguration>{StrategyConfiguration(
+        std::make_optional("STEREO_ONE_CIS_PER_DEVICE"), std::nullopt,
+        std::make_optional(2), std::make_optional(1), std::nullopt)});
+const auto kInvalidStrategyNoDevice = StrategyConfigurationList(
+    std::vector<StrategyConfiguration>{StrategyConfiguration(
+        std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
+        std::make_optional(AudioLocation::STEREO), std::nullopt,
+        std::make_optional(1), std::nullopt)});
+const auto kInvalidStrategyNoChannel = StrategyConfigurationList(
+    std::vector<StrategyConfiguration>{StrategyConfiguration(
+        std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
+        std::make_optional(AudioLocation::STEREO), std::make_optional(2),
+        std::nullopt, std::nullopt)});
+const auto kInvalidStrategyIntMoreBitmask = StrategyConfigurationList(
+    std::vector<StrategyConfiguration>{StrategyConfiguration(
+        std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
+        std::make_optional(AudioLocation::STEREO), std::make_optional(2),
+        std::make_optional(1), std::make_optional(7))});
+const auto kInvalidStrategyIntStereoTwoCisTwoDevice = StrategyConfigurationList(
+    std::vector<StrategyConfiguration>{StrategyConfiguration(
+        std::make_optional("STEREO_ONE_CIS_PER_DEVICE"), std::nullopt,
+        std::make_optional(2), std::make_optional(2), std::make_optional(3))});
+const auto kInvalidStrategyIntMonoTwoCisTwoDevice = StrategyConfigurationList(
+    std::vector<StrategyConfiguration>{StrategyConfiguration(
+        std::make_optional("MONO_ONE_CIS_PER_DEVICE"), std::nullopt,
+        std::make_optional(2), std::make_optional(2), std::make_optional(4))});
+const auto kInvalidStrategyIntBroadcast = StrategyConfigurationList(
+    std::vector<StrategyConfiguration>{StrategyConfiguration(
+        std::make_optional("MONO_ONE_CIS_PER_DEVICE"), std::nullopt,
+        std::make_optional(0), std::make_optional(1), std::make_optional(3))});
+const auto kInvalidStrategyBothStereoMonoInt = StrategyConfigurationList(
+    std::vector<StrategyConfiguration>{StrategyConfiguration(
+        std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
+        std::make_optional(AudioLocation::STEREO), std::make_optional(2),
+        std::make_optional(1), std::make_optional(4))});
 
 // Define valid test list built from above valid components
 // Scenario, Configuration, CodecConfiguration, StrategyConfiguration
@@ -88,11 +191,27 @@
 static const std::vector<CodecConfigurationList> kValidCodecConfigurationList =
     {CodecConfigurationList(
         std::vector<CodecConfiguration>{kValidCodecLC3_16k_1})};
+
 static const std::vector<StrategyConfigurationList>
     kValidStrategyConfigurationList = {
         StrategyConfigurationList(std::vector<StrategyConfiguration>{
             kValidStrategyStereoOneCis, kValidStrategyStereoTwoCis,
-            kValidStrategyMonoOneCis, kValidStrategyBroadcastStereo})};
+            kValidStrategyMonoOneCis, kValidStrategyBroadcastStereo,
+            kValidStrategyStereoOneCisInt, kValidStrategyStereoTwoCisInt,
+            kValidStrategyMonoOneCisInt, kValidStrategyBroadcastStereoInt,
+            kValidStrategyStereoOneCisBoth, kValidStrategyStereoTwoCisBoth,
+            kValidStrategyMonoOneCisBoth, kValidStrategyBroadcastStereoBoth})};
+
+// Define some valid asymmetric scenario list
+static const std::vector<ScenarioList> kValidAsymmetricScenarioList = {
+    ScenarioList(std::vector<Scenario>{kValidAsymmetricScenario})};
+static const std::vector<ConfigurationList> kValidAsymmetricConfigurationList =
+    {ConfigurationList(std::vector<Configuration>{
+        kValidConfigOneChanStereo_16_1, kValidConfigOneChanStereo_32_1})};
+static const std::vector<CodecConfigurationList>
+    kValidAsymmetricCodecConfigurationList = {
+        CodecConfigurationList(std::vector<CodecConfiguration>{
+            kValidCodecLC3_16k_1, kValidCodecLC3_32k_1})};
 
 class BluetoothLeAudioCodecsProviderTest
     : public ::testing::TestWithParam<OffloadSetting> {
@@ -140,6 +259,19 @@
     return le_audio_codec_capabilities;
   }
 
+  std::unordered_map<SessionType, std::vector<CodecInfo>>
+  RunCodecInfoTestCase() {
+    auto& [scenario_lists, configuration_lists, codec_configuration_lists,
+           strategy_configuration_lists] = GetParam();
+    LeAudioOffloadSetting le_audio_offload_setting(
+        scenario_lists, configuration_lists, codec_configuration_lists,
+        strategy_configuration_lists);
+    auto le_audio_codec_capabilities =
+        BluetoothLeAudioCodecsProvider::GetLeAudioCodecInfo(
+            std::make_optional(le_audio_offload_setting));
+    return le_audio_codec_capabilities;
+  }
+
  private:
   static inline OffloadSetting CreateTestCase(
       const ScenarioList& scenario_list,
@@ -270,49 +402,19 @@
   static std::vector<StrategyConfigurationList>
   CreateInvalidStrategyConfigurations() {
     std::vector<StrategyConfigurationList>
-        invalid_strategy_configuration_test_cases;
-    invalid_strategy_configuration_test_cases.push_back(
-        StrategyConfigurationList(
-            std::vector<StrategyConfiguration>{StrategyConfiguration(
-                std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
-                std::make_optional(AudioLocation::STEREO),
-                std::make_optional(2), std::make_optional(2))}));
-
-    invalid_strategy_configuration_test_cases.push_back(
-        StrategyConfigurationList(
-            std::vector<StrategyConfiguration>{StrategyConfiguration(
-                std::make_optional("MONO_ONE_CIS_PER_DEVICE"),
-                std::make_optional(AudioLocation::STEREO),
-                std::make_optional(2), std::make_optional(2))}));
-
-    invalid_strategy_configuration_test_cases.push_back(
-        StrategyConfigurationList(
-            std::vector<StrategyConfiguration>{StrategyConfiguration(
-                std::nullopt, std::make_optional(AudioLocation::STEREO),
-                std::make_optional(2), std::make_optional(1))}));
-
-    invalid_strategy_configuration_test_cases.push_back(
-        StrategyConfigurationList(
-            std::vector<StrategyConfiguration>{StrategyConfiguration(
-                std::make_optional("STEREO_ONE_CIS_PER_DEVICE"), std::nullopt,
-                std::make_optional(2), std::make_optional(1))}));
-
-    invalid_strategy_configuration_test_cases.push_back(
-        StrategyConfigurationList(
-            std::vector<StrategyConfiguration>{StrategyConfiguration(
-                std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
-                std::make_optional(AudioLocation::STEREO), std::nullopt,
-                std::make_optional(1))}));
-
-    invalid_strategy_configuration_test_cases.push_back(
-        StrategyConfigurationList(
-            std::vector<StrategyConfiguration>{StrategyConfiguration(
-                std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
-                std::make_optional(AudioLocation::STEREO),
-                std::make_optional(2), std::nullopt)}));
-
-    invalid_strategy_configuration_test_cases.push_back(
-        StrategyConfigurationList(std::vector<StrategyConfiguration>{}));
+        invalid_strategy_configuration_test_cases = {
+            kInvalidStrategyStereoTwoCisTwoDevice,
+            kInvalidStrategyMonoTwoCisTwoDevice,
+            kInvalidStrategyNoName,
+            kInvalidStrategyNoLocation,
+            kInvalidStrategyNoDevice,
+            kInvalidStrategyNoChannel,
+            kInvalidStrategyIntMoreBitmask,
+            kInvalidStrategyIntStereoTwoCisTwoDevice,
+            kInvalidStrategyIntMonoTwoCisTwoDevice,
+            kInvalidStrategyIntBroadcast,
+            kInvalidStrategyBothStereoMonoInt,
+            StrategyConfigurationList(std::vector<StrategyConfiguration>{})};
 
     return invalid_strategy_configuration_test_cases;
   }
@@ -335,6 +437,39 @@
   ASSERT_TRUE(!le_audio_codec_capabilities.empty());
 }
 
+class ComposeLeAudioAymmetricCodecInfoTest
+    : public BluetoothLeAudioCodecsProviderTest {
+ public:
+};
+
+TEST_P(ComposeLeAudioAymmetricCodecInfoTest, AsymmetricCodecInfoNotEmpty) {
+  Initialize();
+  auto le_audio_codec_info_map = RunCodecInfoTestCase();
+  ASSERT_TRUE(!le_audio_codec_info_map.empty());
+  // Check true asymmetric codec info
+  ASSERT_TRUE(!le_audio_codec_info_map
+                   [SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH]
+                       .empty());
+  ASSERT_TRUE(!le_audio_codec_info_map
+                   [SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH]
+                       .empty());
+  auto required_flag = ConfigurationFlags();
+  required_flag.bitmask |= ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS;
+
+  auto codec_info = le_audio_codec_info_map
+      [SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH][0];
+  ASSERT_EQ(codec_info.transport.getTag(), CodecInfo::Transport::Tag::leAudio);
+  auto& transport =
+      codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
+  ASSERT_EQ(transport.flags, std::make_optional(required_flag));
+
+  codec_info = le_audio_codec_info_map
+      [SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH][0];
+  ASSERT_EQ(codec_info.transport.getTag(), CodecInfo::Transport::Tag::leAudio);
+  transport = codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
+  ASSERT_EQ(transport.flags, std::make_optional(required_flag));
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetScenariosTest);
 INSTANTIATE_TEST_SUITE_P(
     BluetoothLeAudioCodecsProviderTest, GetScenariosTest,
@@ -377,6 +512,15 @@
         kValidScenarioList, kValidConfigurationList,
         kValidCodecConfigurationList, kValidStrategyConfigurationList)));
 
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    ComposeLeAudioAymmetricCodecInfoTest);
+INSTANTIATE_TEST_SUITE_P(
+    BluetoothLeAudioCodecsProviderTest, ComposeLeAudioAymmetricCodecInfoTest,
+    ::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases(
+        kValidAsymmetricScenarioList, kValidAsymmetricConfigurationList,
+        kValidAsymmetricCodecConfigurationList,
+        kValidStrategyConfigurationList)));
+
 int main(int argc, char** argv) {
   ::testing::InitGoogleTest(&argc, argv);
   return RUN_ALL_TESTS();
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml
index eaace78..b6ebbd9 100644
--- a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml
@@ -69,9 +69,9 @@
     <codecConfiguration name="APTX_ADAPTIVE_LEX_96k" codec="APTX_ADAPTIVE_LEX" samplingFrequency="96000" frameDurationUs="10000" octetsPerCodecFrame="816"/>
   </codecConfigurationList>
   <strategyConfigurationList>
-    <strategyConfiguration name="STEREO_ONE_CIS_PER_DEVICE" audioLocation="STEREO" connectedDevice="2" channelCount="1"/>
-    <strategyConfiguration name="STEREO_TWO_CISES_PER_DEVICE" audioLocation="STEREO" connectedDevice="1" channelCount="2"/>
-    <strategyConfiguration name="MONO_ONE_CIS_PER_DEVICE" audioLocation="MONO" connectedDevice="1" channelCount="1"/>
-    <strategyConfiguration name="BROADCAST_STEREO" audioLocation="STEREO" connectedDevice="0" channelCount="2"/>
+    <strategyConfiguration name="STEREO_ONE_CIS_PER_DEVICE" audioLocation="STEREO" connectedDevice="2" channelCount="1" audioChannelAllocation="3"/>
+    <strategyConfiguration name="STEREO_TWO_CISES_PER_DEVICE" audioLocation="STEREO" connectedDevice="1" channelCount="2" audioChannelAllocation="3"/>
+    <strategyConfiguration name="MONO_ONE_CIS_PER_DEVICE" audioLocation="MONO" connectedDevice="1" channelCount="1" audioChannelAllocation="4"/>
+    <strategyConfiguration name="BROADCAST_STEREO" audioLocation="STEREO" connectedDevice="0" channelCount="2" audioChannelAllocation="3"/>
   </strategyConfigurationList>
 </leAudioOffloadSetting>
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd
index 03c8ade..d9ccab5 100644
--- a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd
@@ -56,9 +56,12 @@
   <xs:element name="strategyConfiguration">
     <xs:complexType>
       <xs:attribute name="name" type="xs:string"/>
+      <!-- Deprecated definition of Audio Location, please use audioLocationInt -->
       <xs:attribute name="audioLocation" type="audioLocation"/>
       <xs:attribute name="connectedDevice" type="xs:unsignedByte"/>
       <xs:attribute name="channelCount" type="xs:unsignedByte"/>
+      <!-- Integer Audio Location to populate to audioLocation if present -->
+      <xs:attribute name="audioChannelAllocation" type="xs:int"/>
     </xs:complexType>
   </xs:element>
   <xs:simpleType name="audioLocation">
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
index a882174..b6c2f03 100644
--- a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
@@ -81,10 +81,12 @@
 
   public class StrategyConfiguration {
     ctor public StrategyConfiguration();
+    method public int getAudioChannelAllocation();
     method public aidl.android.hardware.bluetooth.audio.setting.AudioLocation getAudioLocation();
     method public short getChannelCount();
     method public short getConnectedDevice();
     method public String getName();
+    method public void setAudioChannelAllocation(int);
     method public void setAudioLocation(aidl.android.hardware.bluetooth.audio.setting.AudioLocation);
     method public void setChannelCount(short);
     method public void setConnectedDevice(short);
diff --git a/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.fbs b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.fbs
index bde467d..ed9ad49 100644
--- a/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.fbs
+++ b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.fbs
@@ -56,10 +56,9 @@
     HIGH_RELIABILITY = 0x03,
 }
 table AudioSetSubConfiguration {
-    device_cnt: ubyte;
+    ase_channel_cnt: ubyte;
     ase_cnt: ubyte;
     direction: AudioSetConfigurationDirection = SINK;
-    configuration_strategy: AudioSetConfigurationStrategy;
     codec_id : CodecId (required);
     codec_configuration: [CodecSpecificConfiguration] (required);
 }
diff --git a/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.json b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.json
index 404a48a..88e9ce4 100644
--- a/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.json
+++ b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.json
@@ -13,16 +13,12 @@
     "   Codec Configuration parameter types:",
     "     SUPPORTED_SAMPLING_FREQUENCY = 1",
     "     SUPPORTED_FRAME_DURATION = 2",
-    "     SUPPORTED_AUDIO_CHANNEL_ALLOCATION = 3",
     "     SUPPORTED_OCTETS_PER_CODEC_FRAME = 4",
     "     SUPPORTED_CODEC_FRAME_BLOCKS_PER_SDU = 5",
     " Example values which can be used as 'codec_configuration.compound_value'",
     "   Codec Coding formats:",
     "     LC3 = 6",
-    "   ASE Configuration strategies:",
-    "     MONO_ONE_CIS_PER_DEVICE = 0",
-    "     STEREO_TWO_CISES_PER_DEVICE = 1",
-    "     STEREO_ONE_CIS_PER_DEVICE = 2",
+    "     OPUS = 225",
     "   Sampling Frequencies: ",
     "     8000Hz = 1",
     "     11025Hz = 2",
@@ -39,1181 +35,1140 @@
     "     384000Hz = 13",
     "   Frame Durations:",
     "     7500us = 0",
-    "     10000us = 1"
+    "     10000us = 1",
+    "     20000us = 2"
   ],
   "configurations": [
     {
-      "name": "DualDev_OneChanStereoSnk_16_1_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_16_1_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_16_1_1",
-      "codec_config_name": "DualDev_OneChanStereoSnk_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_1"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_16_1_2",
-      "codec_config_name": "DualDev_OneChanStereoSnk_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_2"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_16_2_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_16_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_16_2_1",
-      "codec_config_name": "DualDev_OneChanStereoSnk_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_1"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_16_2_2",
-      "codec_config_name": "DualDev_OneChanStereoSnk_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_16_1_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_16_1_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_16_1_1",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_16_1_2",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_16_2_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_16_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_16_2_1",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_16_2_2",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_2"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_16_1_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1",
+      "name": "One-TwoChan-SnkAse-Lc3_16_1_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_16_1_Balanced_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1",
+      "name": "One-TwoChan-SnkAse-Lc3_16_1_Balanced_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_16_1_1",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1",
+      "name": "One-TwoChan-SnkAse-Lc3_16_1_1",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_1"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_16_1_2",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_16_1",
+      "name": "One-TwoChan-SnkAse-Lc3_16_1_2",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_2"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_16_2_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_16_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_16_2_1",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2_1",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_1"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_16_2_2",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2_2",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_32_1_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_32_1",
+      "name": "One-OneChan-SnkAse-Lc3_32_1_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_32_1",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_32_1_1",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_32_1",
+      "name": "One-OneChan-SnkAse-Lc3_32_1_1",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_32_1",
       "qos_config_name": [
         "QoS_Config_32_1_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_32_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_32_2",
+      "name": "One-OneChan-SnkAse-Lc3_32_1_2",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_32_1",
+      "qos_config_name": [
+        "QoS_Config_32_1_2"
+      ]
+    },
+    {
+      "name": "One-OneChan-SnkAse-Lc3_32_2_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_32_2_1",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_32_2",
+      "name": "One-OneChan-SnkAse-Lc3_32_2_1",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_32_2_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_16_1_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_16_1",
+      "name": "One-OneChan-SnkAse-Lc3_32_2_2",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_32_2",
+      "qos_config_name": [
+        "QoS_Config_32_2_2"
+      ]
+    },
+    {
+      "name": "One-OneChan-SnkAse-Lc3_16_1_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_16_1_1",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_16_1",
+      "name": "One-OneChan-SnkAse-Lc3_16_1_1",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_16_1_2",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_16_1",
+      "name": "One-OneChan-SnkAse-Lc3_16_1_2",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_2"
       ]
     },
     {
-      "name": "DualDev_OneChanMonoSnk_16_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanMonoSnk_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_16_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_16_2",
+      "name": "One-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_16_2_1",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_16_2",
+      "name": "One-OneChan-SnkAse-Lc3_16_2_1",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_16_2_2",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_16_2",
+      "name": "One-OneChan-SnkAse-Lc3_16_2_2",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_2"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_1"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_2",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_2"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_2",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_2"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_1"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_2",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_2"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_1"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_1"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_2",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_2"
       ]
     },
     {
-      "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
-      "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1",
+      "name": "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_1",
-      "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1",
-      "qos_config_name": [
-        "QoS_Config_16_1_1"
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2",
-      "qos_config_name": [
-        "QoS_Config_Low_Latency"
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2",
+      "name": "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_1",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_32_2_1"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_2",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_2",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_2"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_1",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_1"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1",
+      "name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_2",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1",
+      "name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_2",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_2"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1",
+      "name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_1",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_1"
       ]
     },
     {
-      "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_2",
-      "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1",
-      "qos_config_name": [
-        "QoS_Config_16_1_2"
-      ]
-    },
-    {
-      "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-      "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_1",
-      "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2",
-      "qos_config_name": [
-        "QoS_Config_16_2_1"
-      ]
-    },
-    {
-      "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_2",
-      "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2",
-      "qos_config_name": [
-        "QoS_Config_16_2_2"
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1",
-      "qos_config_name": [
-        "QoS_Config_Low_Latency"
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1",
+      "name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_1"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_2",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1",
+      "name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_2",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_2"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_1"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_2",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_2",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_2",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_2",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1",
+      "name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1",
+      "name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_1"
       ]
     },
     {
-      "name": "DualDev_OneChanMonoSrc_16_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanMonoSrc_16_2",
+      "name": "Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSrc_16_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanStereoSrc_16_2",
+      "name": "Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_48_4_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSrc_48_4",
+      "name": "One-OneChan-SrcAse-Lc3_48_4_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SrcAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_48_3_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSrc_48_3",
+      "name": "One-OneChan-SrcAse-Lc3_48_3_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SrcAse-Lc3_48_3",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_48_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSrc_48_2",
+      "name": "One-OneChan-SrcAse-Lc3_48_2_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SrcAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_48_1_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSrc_48_1",
+      "name": "One-OneChan-SrcAse-Lc3_48_1_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SrcAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_32_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSrc_32_2",
+      "name": "One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_32_1_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSrc_32_1",
+      "name": "One-OneChan-SrcAse-Lc3_32_1_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SrcAse-Lc3_32_1",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_24_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSrc_24_2",
+      "name": "One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SrcAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_24_1_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSrc_24_1",
+      "name": "One-OneChan-SrcAse-Lc3_24_1_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SrcAse-Lc3_24_1",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSrc_16_2",
+      "name": "One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_16_1_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSrc_16_1",
+      "name": "One-OneChan-SrcAse-Lc3_16_1_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_2",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1",
+      "name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_2",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "qos_config_name": [
         "QoS_Config_16_1_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2",
+      "name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2",
+      "name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_2",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2",
+      "name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_2",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_16_2_2"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_24_1_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_24_1",
+      "name": "Two-OneChan-SnkAse-Lc3_24_1_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_24_1_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_24_1",
+      "name": "One-TwoChan-SnkAse-Lc3_24_1_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_24_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_24_1_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_24_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_24_2_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_24_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_24_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_24_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_24_2_2",
-      "codec_config_name": "DualDev_OneChanStereoSnk_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_24_2_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_24_2_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_24_2_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_24_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_24_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_24_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_24_2_2",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_24_2_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_24_2_2"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_24_2_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_24_2",
+      "name": "One-TwoChan-SnkAse-Lc3_24_2_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_24_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_24_2",
+      "name": "One-TwoChan-SnkAse-Lc3_24_2_Balanced_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_24_2_2",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_24_2",
+      "name": "One-TwoChan-SnkAse-Lc3_24_2_2",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_24_2_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_24_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_24_2",
+      "name": "One-OneChan-SnkAse-Lc3_24_2_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_24_2_2",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_24_2",
+      "name": "One-OneChan-SnkAse-Lc3_24_2_2",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_24_2_2"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_32_2_1"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_32_2_1"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_32_2_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_32_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_32_1_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_32_1",
+      "name": "Two-OneChan-SnkAse-Lc3_32_1_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_32_1_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_32_1",
+      "name": "One-TwoChan-SnkAse-Lc3_32_1_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_32_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_32_2_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_32_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_32_1_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_32_1",
+      "name": "Two-OneChan-SnkAse-Lc3_32_1_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-      "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2",
+      "name": "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_1",
-      "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2",
+      "name": "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_32_2_1"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_32_2_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2",
+      "name": "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2",
+      "name": "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_32_2_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2",
+      "name": "One-TwoChan-SnkAse-Lc3_32_2_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2",
-      "qos_config_name": [
-        "QoS_Config_32_2_1"
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_32_2_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_32_2",
-      "qos_config_name": [
-        "QoS_Config_Low_Latency"
-      ]
-    },
-    {
-      "name": "DualDev_OneChanStereoSnk_48_4_High_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_4",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4_High_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_1",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_4",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_48_4_1"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_2",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_4",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_48_4_2"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_3_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_3",
+      "name": "Two-OneChan-SnkAse-Lc3_48_3_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_3",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_3_High_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_3",
+      "name": "Two-OneChan-SnkAse-Lc3_48_3_High_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_3",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_3_2",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_3",
+      "name": "Two-OneChan-SnkAse-Lc3_48_3_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_3",
       "qos_config_name": [
         "QoS_Config_48_3_2"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_2_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_2_High_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_2_High_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_2_2",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_2_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_48_2_2"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_1_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_1",
+      "name": "Two-OneChan-SnkAse-Lc3_48_1_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_1_High_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_1",
+      "name": "Two-OneChan-SnkAse-Lc3_48_1_High_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_1_2",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_1",
+      "name": "Two-OneChan-SnkAse-Lc3_48_1_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_48_1_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_4_High_Reliability",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_4",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4_High_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_4_1",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_4",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4_1",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_48_4_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_4_2",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_4",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_48_4_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_3_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_3",
+      "name": "Two-OneChan-SnkAse-Lc3_48_3_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_3",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_3_High_Reliability",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_3",
+      "name": "Two-OneChan-SnkAse-Lc3_48_3_High_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_3",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_3_2",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_3",
+      "name": "Two-OneChan-SnkAse-Lc3_48_3_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_3",
       "qos_config_name": [
         "QoS_Config_48_3_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_2_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_2_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_2_High_Reliability",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_2_High_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_2_2",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_2_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_48_2_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_1_Low_Latency",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_1",
+      "name": "Two-OneChan-SnkAse-Lc3_48_1_Low_Latency",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_1_High_Reliability",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_1",
+      "name": "Two-OneChan-SnkAse-Lc3_48_1_High_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_1_2",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_1",
+      "name": "Two-OneChan-SnkAse-Lc3_48_1_2",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_48_1_2"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_High_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4_High_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_1",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4_1",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_48_4_1"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_2",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4_2",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_48_4_2"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_3_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_3",
+      "name": "One-TwoChan-SnkAse-Lc3_48_3_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_3",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_3_High_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_3",
+      "name": "One-TwoChan-SnkAse-Lc3_48_3_High_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_3",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_3_2",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_3",
+      "name": "One-TwoChan-SnkAse-Lc3_48_3_2",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_3",
       "qos_config_name": [
         "QoS_Config_48_3_2"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_2_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_2_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_2_High_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_2_High_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_2_2",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_2_2",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_48_2_2"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_1_Low_Latency",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_1",
+      "name": "One-TwoChan-SnkAse-Lc3_48_1_Low_Latency",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_1_High_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_1",
+      "name": "One-TwoChan-SnkAse-Lc3_48_1_High_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_1_2",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_1",
+      "name": "One-TwoChan-SnkAse-Lc3_48_1_2",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_48_1_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_48_4_High_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_48_4",
+      "name": "One-OneChan-SnkAse-Lc3_48_4_High_Reliability",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_48_4_1",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_48_4",
+      "name": "One-OneChan-SnkAse-Lc3_48_4_1",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_48_4_1"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_48_4_2",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_48_4",
+      "name": "One-OneChan-SnkAse-Lc3_48_4_2",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_48_4",
       "qos_config_name": [
         "QoS_Config_48_4_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_48_3_High_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_48_3",
+      "name": "One-OneChan-SnkAse-Lc3_48_3_High_Reliability",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_48_3",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_48_3_2",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_48_3",
+      "name": "One-OneChan-SnkAse-Lc3_48_3_2",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_48_3",
       "qos_config_name": [
         "QoS_Config_48_3_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_48_2_High_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_48_2",
+      "name": "One-OneChan-SnkAse-Lc3_48_2_High_Reliability",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_48_2_2",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_48_2",
+      "name": "One-OneChan-SnkAse-Lc3_48_2_2",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_48_2_2"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_48_1_High_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_48_1",
+      "name": "One-OneChan-SnkAse-Lc3_48_1_High_Reliability",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_High_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_48_1_2",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_48_1",
+      "name": "One-OneChan-SnkAse-Lc3_48_1_2",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_48_1_2"
       ]
@@ -1289,176 +1244,155 @@
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_1_OneChanMonoSrc_24_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_1_OneChanMonoSrc_16_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_4_1_OneChanMonoSrc_32_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2",
+      "name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_4_1_OneChanMonoSrc_24_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2",
+      "name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_4_1_OneChanMonoSrc_16_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2",
+      "name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+      "codec_config_name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_48_4_1_OneChanMonoSrc_32_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_32_2",
-      "qos_config_name": [
-        "QoS_Config_Balanced_Reliability"
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_48_4_1_OneChanMonoSrc_24_2_1_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_24_2",
-      "qos_config_name": [
-        "QoS_Config_Balanced_Reliability"
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_48_4_1_OneChanMonoSrc_16_2_Balanced_Reliability",
-      "codec_config_name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_16_2",
-      "qos_config_name": [
-        "QoS_Config_Balanced_Reliability"
-      ]
-    },
-    {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1",
+      "name": "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Low_Latency",
+      "codec_config_name": "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1",
+      "name": "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Balanced_Reliability",
+      "codec_config_name": "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Low_Latency",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2",
+      "name": "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Low_Latency",
+      "codec_config_name": "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_Low_Latency"
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Balanced_Reliability",
-      "codec_config_name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2",
+      "name": "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Balanced_Reliability",
+      "codec_config_name": "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2",
       "qos_config_name": [
         "QoS_Config_Balanced_Reliability"
       ]
@@ -1495,13 +1429,11 @@
   ],
   "codec_configurations": [
     {
-      "name": "DualDev_OneChanStereoSnk_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_16_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -1527,18 +1459,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -1557,18 +1477,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_16_1",
+      "name": "Two-OneChan-SnkAse-Lc3_16_1",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -1594,18 +1513,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -1624,152 +1531,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanStereoSnk_16_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_16_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -1795,18 +1567,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -1825,18 +1585,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_16_1",
+      "name": "One-TwoChan-SnkAse-Lc3_16_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -1862,18 +1621,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -1892,18 +1639,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSrc_16_2",
+      "name": "Two-OneChan-SrcAse-Lc3_16_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 2,
           "direction": "SOURCE",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -1929,18 +1675,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -1959,15 +1693,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_24_2",
+      "name": "One-OneChan-SrcAse-Lc3_24_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -1995,13 +1729,109 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
+              "name": "octets_per_codec_frame",
+              "type": 4,
               "compound_value": {
                 "value": [
-                  1,
-                  0,
-                  0,
+                  60,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "Two-OneChan-SnkAse-Lc3_32_2",
+      "subconfigurations": [
+        {
+          "ase_cnt": 2,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  6
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  80,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "Two-OneChan-SnkAse-Lc3_32_1",
+      "subconfigurations": [
+        {
+          "ase_cnt": 2,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  6
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
                   0
                 ]
               }
@@ -2025,18 +1855,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_32_2",
+      "name": "One-OneChan-SnkAse-Lc3_32_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
-          "ase_cnt": 2,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -2062,18 +1891,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -2092,18 +1909,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_32_1",
+      "name": "One-OneChan-SnkAse-Lc3_32_1",
       "subconfigurations": [
         {
-          "device_cnt": 2,
-          "ase_cnt": 2,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -2129,18 +1945,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -2159,18 +1963,537 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_32_2",
+      "name": "One-OneChan-SnkAse-Lc3_16_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  40,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "One-OneChan-SnkAse-Lc3_16_1",
+      "subconfigurations": [
+        {
+          "ase_cnt": 1,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  0
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  30,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
+      "subconfigurations": [
+        {
+          "ase_cnt": 2,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  40,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        },
+        {
+          "ase_cnt": 1,
+          "direction": "SOURCE",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  40,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2",
+      "subconfigurations": [
+        {
+          "ase_cnt": 2,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  40,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        },
+        {
+          "ase_cnt": 2,
+          "direction": "SOURCE",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  40,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1",
+      "subconfigurations": [
+        {
+          "ase_cnt": 2,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  0
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  30,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        },
+        {
+          "ase_cnt": 2,
+          "direction": "SOURCE",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  0
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  30,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
+      "subconfigurations": [
+        {
+          "ase_cnt": 2,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  0
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  30,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        },
+        {
+          "ase_cnt": 1,
+          "direction": "SOURCE",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  0
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  30,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2",
+      "subconfigurations": [
+        {
+          "ase_cnt": 1,
+          "direction": "SINK",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -2196,18 +2519,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -2226,344 +2537,10 @@
                 ]
               }
             }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_32_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  60,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "DualDev_OneChanMonoSnk_16_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 2,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_16_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_16_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 2,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -2577,710 +2554,6 @@
               "type": 1,
               "compound_value": {
                 "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 2,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 2,
-          "ase_cnt": 2,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 2,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 2,
-          "ase_cnt": 2,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 2,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 2,
-          "ase_cnt": 4,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 2,
-          "ase_cnt": 4,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
                   6
                 ]
               }
@@ -3295,18 +2568,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -3325,847 +2586,15 @@
                 ]
               }
             }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  40,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  30,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
           "codec_id": {
@@ -4193,18 +2622,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -4223,10 +2640,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -4254,18 +2671,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -4284,15 +2689,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1",
+      "name": "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
           "codec_id": {
@@ -4320,18 +2725,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -4350,10 +2743,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -4381,18 +2774,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -4411,16 +2792,65 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "DualDev_OneChanMonoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
-          "ase_cnt": 2,
+          "ase_cnt": 1,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  40,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 2
+        },
+        {
+          "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
             "coding_format": 6,
@@ -4447,18 +2877,163 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
+              "name": "octets_per_codec_frame",
+              "type": 4,
               "compound_value": {
                 "value": [
-                  1,
-                  0,
-                  0,
+                  40,
                   0
                 ]
               }
             },
             {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
+      "subconfigurations": [
+        {
+          "ase_cnt": 1,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  0
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  30,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 2
+        },
+        {
+          "ase_cnt": 1,
+          "direction": "SOURCE",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  0
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  30,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2",
+      "subconfigurations": [
+        {
+          "ase_cnt": 1,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -4477,15 +3052,167 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
+        },
+        {
+          "ase_cnt": 1,
+          "direction": "SOURCE",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  40,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_48_4",
+      "name": "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
+          "ase_cnt": 1,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  0
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  30,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        },
+        {
+          "ase_cnt": 1,
+          "direction": "SOURCE",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  3
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  0
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  30,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "One-OneChan-SrcAse-Lc3_48_4",
+      "subconfigurations": [
+        {
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -4513,18 +3240,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -4543,15 +3258,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_48_3",
+      "name": "One-OneChan-SrcAse-Lc3_48_3",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -4579,18 +3294,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -4609,15 +3312,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_48_2",
+      "name": "One-OneChan-SrcAse-Lc3_48_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -4645,18 +3348,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -4675,15 +3366,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_48_1",
+      "name": "One-OneChan-SrcAse-Lc3_48_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -4711,18 +3402,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -4741,15 +3420,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_32_2",
+      "name": "One-OneChan-SrcAse-Lc3_32_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -4777,18 +3456,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -4807,15 +3474,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_32_1",
+      "name": "One-OneChan-SrcAse-Lc3_32_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -4843,18 +3510,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -4873,15 +3528,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_24_2",
+      "name": "One-OneChan-SrcAse-Lc3_24_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -4904,84 +3559,6 @@
               "type": 2,
               "compound_value": {
                 "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  60,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSrc_24_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  5
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
                   0
                 ]
               }
@@ -5005,15 +3582,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_16_2",
+      "name": "One-OneChan-SrcAse-Lc3_16_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -5041,18 +3618,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5071,15 +3636,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSrc_16_1",
+      "name": "One-OneChan-SrcAse-Lc3_16_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -5107,18 +3672,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5137,18 +3690,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -5174,18 +3726,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5204,18 +3744,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_3",
+      "name": "Two-OneChan-SnkAse-Lc3_48_3",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -5241,18 +3780,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5271,18 +3798,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -5308,18 +3834,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5338,18 +3852,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_1",
+      "name": "Two-OneChan-SnkAse-Lc3_48_1",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -5375,18 +3888,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5405,18 +3906,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_4",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4",
       "subconfigurations": [
         {
-          "device_cnt": 1,
-          "ase_cnt": 2,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -5442,18 +3942,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5472,18 +3960,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_3",
+      "name": "One-TwoChan-SnkAse-Lc3_48_3",
       "subconfigurations": [
         {
-          "device_cnt": 1,
-          "ase_cnt": 2,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -5509,18 +3996,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5539,18 +4014,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
-          "ase_cnt": 2,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -5576,18 +4050,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5606,18 +4068,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_1",
+      "name": "One-TwoChan-SnkAse-Lc3_48_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
-          "ase_cnt": 2,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -5643,18 +4104,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5673,18 +4122,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4",
+      "name": "One-OneChan-SnkAse-Lc3_48_4",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -5710,18 +4158,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5740,18 +4176,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_3",
+      "name": "One-OneChan-SnkAse-Lc3_48_3",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -5777,18 +4212,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5807,18 +4230,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_2",
+      "name": "One-OneChan-SnkAse-Lc3_48_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -5844,18 +4266,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5874,18 +4284,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_1",
+      "name": "One-OneChan-SnkAse-Lc3_48_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -5911,18 +4320,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -5941,275 +4338,8 @@
                 ]
               }
             }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_48_4",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  8
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  120,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_48_3",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  8
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  90,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_48_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  8
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  100,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_48_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  8
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  75,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
@@ -6217,10 +4347,8 @@
       "name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -6246,18 +4374,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -6276,7 +4392,8 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
@@ -6284,10 +4401,8 @@
       "name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_1",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -6313,18 +4428,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -6343,7 +4446,8 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
@@ -6351,10 +4455,8 @@
       "name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 2,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -6380,18 +4482,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -6410,7 +4500,8 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
@@ -6418,10 +4509,8 @@
       "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -6447,18 +4536,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -6477,15 +4554,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_32_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
           "codec_id": {
@@ -6513,18 +4590,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -6543,10 +4608,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         },
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SOURCE",
           "codec_id": {
@@ -6574,18 +4639,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -6604,15 +4657,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_24_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
           "codec_id": {
@@ -6640,18 +4693,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -6670,10 +4711,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         },
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SOURCE",
           "codec_id": {
@@ -6701,23 +4742,11 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
                 "value": [
-                  80,
+                  60,
                   0
                 ]
               }
@@ -6731,15 +4760,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_16_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
           "codec_id": {
@@ -6767,18 +4796,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -6797,10 +4814,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         },
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SOURCE",
           "codec_id": {
@@ -6828,23 +4845,11 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
                 "value": [
-                  80,
+                  40,
                   0
                 ]
               }
@@ -6858,15 +4863,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
           "codec_id": {
@@ -6894,18 +4899,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -6924,10 +4917,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -6955,18 +4948,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -6985,15 +4966,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
           "codec_id": {
@@ -7021,18 +5002,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -7051,10 +5020,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -7082,23 +5051,11 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
                 "value": [
-                  80,
+                  60,
                   0
                 ]
               }
@@ -7112,15 +5069,15 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2",
+      "name": "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
           "codec_id": {
@@ -7148,18 +5105,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -7178,10 +5123,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -7209,23 +5154,11 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
                 "value": [
-                  80,
+                  40,
                   0
                 ]
               }
@@ -7239,18 +5172,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_32_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
-          "ase_cnt": 4,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -7276,18 +5208,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -7306,10 +5226,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -7337,18 +5257,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -7367,18 +5275,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_24_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
-          "ase_cnt": 4,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -7404,18 +5311,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -7434,10 +5329,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -7465,23 +5360,11 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
                 "value": [
-                  80,
+                  60,
                   0
                 ]
               }
@@ -7495,18 +5378,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_16_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
-          "ase_cnt": 4,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -7532,18 +5414,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -7562,10 +5432,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -7593,23 +5463,11 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
                 "value": [
-                  80,
+                  40,
                   0
                 ]
               }
@@ -7623,18 +5481,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -7660,18 +5517,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -7690,397 +5535,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  8
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  120,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  5
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  8
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  120,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  8
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  120,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -8108,18 +5566,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -8138,18 +5584,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_24_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -8175,18 +5620,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -8205,10 +5638,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -8236,23 +5669,11 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
                 "value": [
-                  80,
+                  60,
                   0
                 ]
               }
@@ -8266,18 +5687,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_16_2",
+      "name": "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -8303,18 +5723,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -8333,10 +5741,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -8364,23 +5772,11 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
                 "value": [
-                  80,
+                  40,
                   0
                 ]
               }
@@ -8394,18 +5790,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2",
+      "name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
-          "ase_cnt": 2,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -8431,18 +5826,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -8461,10 +5844,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -8492,18 +5875,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -8522,18 +5893,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2",
+      "name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
-          "ase_cnt": 2,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -8559,18 +5929,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -8589,10 +5947,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -8620,23 +5978,11 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
                 "value": [
-                  80,
+                  60,
                   0
                 ]
               }
@@ -8650,18 +5996,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2",
+      "name": "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
-          "ase_cnt": 2,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -8687,18 +6032,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -8717,10 +6050,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -8748,23 +6081,11 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
                 "value": [
-                  80,
+                  40,
                   0
                 ]
               }
@@ -8778,399 +6099,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_32_2",
+      "name": "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  8
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  120,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_24_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  8
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  120,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  5
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_16_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  8
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  120,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  3
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SOURCE",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -9196,18 +6135,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -9226,13 +6153,12 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -9258,18 +6184,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -9288,18 +6202,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2",
+      "name": "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SOURCE",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -9325,18 +6238,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -9355,13 +6256,12 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -9387,18 +6287,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -9417,7 +6305,8 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
@@ -9425,10 +6314,8 @@
       "name": "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -9454,18 +6341,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -9484,7 +6359,8 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
@@ -9492,10 +6368,8 @@
       "name": "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60octs_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -9521,18 +6395,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -9551,10 +6413,10 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
           "codec_id": {
@@ -9582,18 +6444,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -9612,7 +6462,8 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
@@ -9620,10 +6471,8 @@
       "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -9649,18 +6498,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -9679,13 +6516,12 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         },
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SOURCE",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -9711,18 +6547,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -9741,18 +6565,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_24_2",
+      "name": "Two-OneChan-SnkAse-Lc3_24_2",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -9778,18 +6601,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -9808,18 +6619,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "DualDev_OneChanStereoSnk_24_1",
+      "name": "Two-OneChan-SnkAse-Lc3_24_1",
       "subconfigurations": [
         {
-          "device_cnt": 2,
           "ase_cnt": 2,
           "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -9845,18 +6655,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -9875,18 +6673,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 1
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_24_2",
+      "name": "One-TwoChan-SnkAse-Lc3_24_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
-          "ase_cnt": 2,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -9912,18 +6709,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -9942,18 +6727,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "SingleDev_OneChanStereoSnk_24_1",
+      "name": "One-TwoChan-SnkAse-Lc3_24_1",
       "subconfigurations": [
         {
-          "device_cnt": 1,
-          "ase_cnt": 2,
+          "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -9979,18 +6763,6 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
               "name": "octets_per_codec_frame",
               "type": 4,
               "compound_value": {
@@ -10009,18 +6781,17 @@
                 ]
               }
             }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     },
     {
-      "name": "SingleDev_TwoChanStereoSnk_24_2",
+      "name": "One-OneChan-SnkAse-Lc3_24_2",
       "subconfigurations": [
         {
-          "device_cnt": 1,
           "ase_cnt": 1,
           "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
           "codec_id": {
             "coding_format": 6,
             "vendor_company_id": 0,
@@ -10046,13 +6817,521 @@
               }
             },
             {
-              "name": "audio_channel_allocation",
-              "type": 3,
+              "name": "octets_per_codec_frame",
+              "type": 4,
               "compound_value": {
                 "value": [
-                  3,
-                  0,
-                  0,
+                  60,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2",
+      "subconfigurations": [
+        {
+          "ase_cnt": 2,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  6
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  80,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        },
+        {
+          "ase_cnt": 2,
+          "direction": "SOURCE",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  6
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  80,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2",
+      "subconfigurations": [
+        {
+          "ase_cnt": 2,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  6
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  80,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        },
+        {
+          "ase_cnt": 1,
+          "direction": "SOURCE",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  6
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  80,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2",
+      "subconfigurations": [
+        {
+          "ase_cnt": 1,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  6
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  80,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 2
+        },
+        {
+          "ase_cnt": 1,
+          "direction": "SOURCE",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  6
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  80,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2",
+      "subconfigurations": [
+        {
+          "ase_cnt": 1,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  6
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  80,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        },
+        {
+          "ase_cnt": 1,
+          "direction": "SOURCE",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  6
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  80,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 1
+        }
+      ]
+    },
+    {
+      "name": "One-TwoChan-SnkAse-Lc3_32_2",
+      "subconfigurations": [
+        {
+          "ase_cnt": 1,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  6
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            },
+            {
+              "name": "octets_per_codec_frame",
+              "type": 4,
+              "compound_value": {
+                "value": [
+                  80,
+                  0
+                ]
+              }
+            },
+            {
+              "name": "codec_frame_blocks_per_sdu",
+              "type": 5,
+              "compound_value": {
+                "value": [
+                  1
+                ]
+              }
+            }
+          ],
+          "ase_channel_cnt": 2
+        }
+      ]
+    },
+    {
+      "name": "One-TwoChan-SnkAse-Lc3_32_1",
+      "subconfigurations": [
+        {
+          "ase_cnt": 1,
+          "direction": "SINK",
+          "codec_id": {
+            "coding_format": 6,
+            "vendor_company_id": 0,
+            "vendor_codec_id": 0
+          },
+          "codec_configuration": [
+            {
+              "name": "sampling_frequency",
+              "type": 1,
+              "compound_value": {
+                "value": [
+                  6
+                ]
+              }
+            },
+            {
+              "name": "frame_duration",
+              "type": 2,
+              "compound_value": {
+                "value": [
                   0
                 ]
               }
@@ -10076,1174 +7355,8 @@
                 ]
               }
             }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_24_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  5
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  45,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_24_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  5
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  60,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 2,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 2,
-          "ase_cnt": 2,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 2,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 2,
-          "ase_cnt": 4,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        },
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SOURCE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_32_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_TwoChanStereoSnk_32_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 1,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  3,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  60,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanStereoSnk_32_2",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  80,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    {
-      "name": "SingleDev_OneChanStereoSnk_32_1",
-      "subconfigurations": [
-        {
-          "device_cnt": 1,
-          "ase_cnt": 2,
-          "direction": "SINK",
-          "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE",
-          "codec_id": {
-            "coding_format": 6,
-            "vendor_company_id": 0,
-            "vendor_codec_id": 0
-          },
-          "codec_configuration": [
-            {
-              "name": "sampling_frequency",
-              "type": 1,
-              "compound_value": {
-                "value": [
-                  6
-                ]
-              }
-            },
-            {
-              "name": "frame_duration",
-              "type": 2,
-              "compound_value": {
-                "value": [
-                  0
-                ]
-              }
-            },
-            {
-              "name": "audio_channel_allocation",
-              "type": 3,
-              "compound_value": {
-                "value": [
-                  1,
-                  0,
-                  0,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "octets_per_codec_frame",
-              "type": 4,
-              "compound_value": {
-                "value": [
-                  60,
-                  0
-                ]
-              }
-            },
-            {
-              "name": "codec_frame_blocks_per_sdu",
-              "type": 5,
-              "compound_value": {
-                "value": [
-                  1
-                ]
-              }
-            }
-          ]
+          ],
+          "ase_channel_cnt": 2
         }
       ]
     }
@@ -11377,6 +7490,5 @@
       "retransmission_number": 0,
       "max_transport_latency": 0
     }
-
   ]
 }
diff --git a/bluetooth/audio/utils/le_audio_configuration_set/audio_set_scenarios.json b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_scenarios.json
index a28c6cd..448adca 100644
--- a/bluetooth/audio/utils/le_audio_configuration_set/audio_set_scenarios.json
+++ b/bluetooth/audio/utils/le_audio_configuration_set/audio_set_scenarios.json
@@ -8,251 +8,206 @@
     {
       "name": "Conversational",
       "configurations": [
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_2",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_2",
-        "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
-        "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
-        "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
-        "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_1",
-        "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_1",
-        "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
-        "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_1",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_2",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_2",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1",
-        "DualDev_OneChanMonoSrc_16_2_Balanced_Reliability",
-        "SingleDev_OneChanStereoSrc_16_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_48_4_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_48_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_48_3_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_48_1_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_32_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_32_1_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_24_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_24_1_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_16_1_Balanced_Reliability",
-        "VND_SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32khz_Server_Prefered_1",
-        "VND_SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32khz_60oct_R3_L22_1",
-        "DualDev_OneChanMonoSnk_16_2_Balanced_Reliability",
-        "SingleDev_OneChanStereoSnk_16_2_Balanced_Reliability",
-        "SingleDev_TwoChanStereoSnk_16_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSnk_16_2_Balanced_Reliability"
+        "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1",
+        "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1",
+        "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_2",
+        "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_1",
+        "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_2",
+        "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+        "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
+        "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_1",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_1",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_2",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_1",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_2",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
+        "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+        "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
+        "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
+        "Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_48_4_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_48_2_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_48_3_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_48_1_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_32_1_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_24_1_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_16_1_Balanced_Reliability",
+        "VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60oct_R3_L22_1",
+        "Two-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability",
+        "One-TwoChan-SnkAse-Lc3_16_2_Balanced_Reliability",
+        "One-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability"
       ]
     },
     {
       "name": "Media",
       "configurations": [
-        "DualDev_OneChanStereoSnk_48_4_High_Reliability",
-        "DualDev_OneChanStereoSnk_48_4_2",
-        "DualDev_OneChanStereoSnk_48_2_High_Reliability",
-        "DualDev_OneChanStereoSnk_48_2_2",
-        "DualDev_OneChanStereoSnk_48_3_High_Reliability",
-        "DualDev_OneChanStereoSnk_48_3_2",
-        "DualDev_OneChanStereoSnk_48_1_High_Reliability",
-        "DualDev_OneChanStereoSnk_48_1_2",
-        "DualDev_OneChanStereoSnk_24_2_Balanced_Reliability",
-        "DualDev_OneChanStereoSnk_24_2_2",
-        "DualDev_OneChanStereoSnk_16_2_Balanced_Reliability",
-        "DualDev_OneChanStereoSnk_16_2_2",
-        "DualDev_OneChanStereoSnk_16_1_Balanced_Reliability",
-        "DualDev_OneChanStereoSnk_16_1_2",
-        "SingleDev_OneChanStereoSnk_48_4_High_Reliability",
-        "SingleDev_OneChanStereoSnk_48_4_2",
-        "SingleDev_OneChanStereoSnk_48_2_High_Reliability",
-        "SingleDev_OneChanStereoSnk_48_2_2",
-        "SingleDev_OneChanStereoSnk_48_3_High_Reliability",
-        "SingleDev_OneChanStereoSnk_48_3_2",
-        "SingleDev_OneChanStereoSnk_48_1_High_Reliability",
-        "SingleDev_OneChanStereoSnk_48_1_2",
-        "SingleDev_OneChanStereoSnk_24_2_Balanced_Reliability",
-        "SingleDev_OneChanStereoSnk_24_2_2",
-        "SingleDev_OneChanStereoSnk_16_2_Balanced_Reliability",
-        "SingleDev_OneChanStereoSnk_16_2_2",
-        "SingleDev_OneChanStereoSnk_16_1_Balanced_Reliability",
-        "SingleDev_OneChanStereoSnk_16_1_2",
-        "SingleDev_TwoChanStereoSnk_48_4_High_Reliability",
-        "SingleDev_TwoChanStereoSnk_48_4_2",
-        "SingleDev_TwoChanStereoSnk_48_4_High_Reliability",
-        "SingleDev_TwoChanStereoSnk_48_4_2",
-        "SingleDev_TwoChanStereoSnk_48_2_High_Reliability",
-        "SingleDev_TwoChanStereoSnk_48_2_2",
-        "SingleDev_TwoChanStereoSnk_48_3_High_Reliability",
-        "SingleDev_TwoChanStereoSnk_48_3_2",
-        "SingleDev_TwoChanStereoSnk_48_1_High_Reliability",
-        "SingleDev_TwoChanStereoSnk_48_1_2",
-        "SingleDev_TwoChanStereoSnk_24_2_Balanced_Reliability",
-        "SingleDev_TwoChanStereoSnk_24_2_2",
-        "SingleDev_TwoChanStereoSnk_16_2_Balanced_Reliability",
-        "SingleDev_TwoChanStereoSnk_16_2_2",
-        "SingleDev_TwoChanStereoSnk_16_1_Balanced_Reliability",
-        "SingleDev_TwoChanStereoSnk_16_1_2",
-        "SingleDev_OneChanMonoSnk_48_4_High_Reliability",
-        "SingleDev_OneChanMonoSnk_48_4_2",
-        "SingleDev_OneChanMonoSnk_48_2_High_Reliability",
-        "SingleDev_OneChanMonoSnk_48_2_2",
-        "SingleDev_OneChanMonoSnk_48_3_High_Reliability",
-        "SingleDev_OneChanMonoSnk_48_3_2",
-        "SingleDev_OneChanMonoSnk_48_1_High_Reliability",
-        "SingleDev_OneChanMonoSnk_48_1_2",
-        "SingleDev_OneChanMonoSnk_32_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSnk_32_2_2",
-        "SingleDev_OneChanMonoSnk_32_1_Balanced_Reliability",
-        "SingleDev_OneChanMonoSnk_32_1_2",
-        "SingleDev_OneChanMonoSnk_24_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSnk_24_2_2",
-        "SingleDev_OneChanMonoSnk_16_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSnk_16_2_2",
-        "SingleDev_OneChanMonoSnk_16_1_Balanced_Reliability",
-        "SingleDev_OneChanMonoSnk_16_1_2",
+        "Two-OneChan-SnkAse-Lc3_48_4_High_Reliability",
+        "Two-OneChan-SnkAse-Lc3_48_4_2",
+        "Two-OneChan-SnkAse-Lc3_48_2_High_Reliability",
+        "Two-OneChan-SnkAse-Lc3_48_2_2",
+        "Two-OneChan-SnkAse-Lc3_48_3_High_Reliability",
+        "Two-OneChan-SnkAse-Lc3_48_3_2",
+        "Two-OneChan-SnkAse-Lc3_48_1_High_Reliability",
+        "Two-OneChan-SnkAse-Lc3_48_1_2",
+        "Two-OneChan-SnkAse-Lc3_24_2_Balanced_Reliability",
+        "Two-OneChan-SnkAse-Lc3_24_2_2",
+        "Two-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability",
+        "Two-OneChan-SnkAse-Lc3_16_2_2",
+        "Two-OneChan-SnkAse-Lc3_16_1_Balanced_Reliability",
+        "Two-OneChan-SnkAse-Lc3_16_1_2",
+        "One-TwoChan-SnkAse-Lc3_48_4_High_Reliability",
+        "One-TwoChan-SnkAse-Lc3_48_4_2",
+        "One-TwoChan-SnkAse-Lc3_48_2_High_Reliability",
+        "One-TwoChan-SnkAse-Lc3_48_2_2",
+        "One-TwoChan-SnkAse-Lc3_48_3_High_Reliability",
+        "One-TwoChan-SnkAse-Lc3_48_3_2",
+        "One-TwoChan-SnkAse-Lc3_48_1_High_Reliability",
+        "One-TwoChan-SnkAse-Lc3_48_1_2",
+        "One-TwoChan-SnkAse-Lc3_24_2_Balanced_Reliability",
+        "One-TwoChan-SnkAse-Lc3_24_2_2",
+        "One-TwoChan-SnkAse-Lc3_16_2_Balanced_Reliability",
+        "One-TwoChan-SnkAse-Lc3_16_2_2",
+        "One-TwoChan-SnkAse-Lc3_16_1_Balanced_Reliability",
+        "One-TwoChan-SnkAse-Lc3_16_1_2",
+        "One-OneChan-SnkAse-Lc3_48_4_High_Reliability",
+        "One-OneChan-SnkAse-Lc3_48_4_2",
+        "One-OneChan-SnkAse-Lc3_48_2_High_Reliability",
+        "One-OneChan-SnkAse-Lc3_48_2_2",
+        "One-OneChan-SnkAse-Lc3_48_3_High_Reliability",
+        "One-OneChan-SnkAse-Lc3_48_3_2",
+        "One-OneChan-SnkAse-Lc3_48_1_High_Reliability",
+        "One-OneChan-SnkAse-Lc3_48_1_2",
+        "One-OneChan-SnkAse-Lc3_32_2_Balanced_Reliability",
+        "One-OneChan-SnkAse-Lc3_32_2_2",
+        "One-OneChan-SnkAse-Lc3_32_1_Balanced_Reliability",
+        "One-OneChan-SnkAse-Lc3_32_1_2",
+        "One-OneChan-SnkAse-Lc3_24_2_Balanced_Reliability",
+        "One-OneChan-SnkAse-Lc3_24_2_2",
+        "One-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability",
+        "One-OneChan-SnkAse-Lc3_16_2_2",
+        "One-OneChan-SnkAse-Lc3_16_1_Balanced_Reliability",
+        "One-OneChan-SnkAse-Lc3_16_1_2",
         "VND_DualDev_OneChanStereoSnk_48khz_100octs_High_Reliability_1",
         "VND_DualDev_OneChanStereoSnk_48khz_100octs_R15_L70_1",
         "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_High_Reliability_1",
         "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_R15_L70_1",
         "VND_SingleDev_OneChanStereoSnk_48khz_100octs_High_Reliability_1",
         "VND_SingleDev_OneChanStereoSnk_48khz_100octs_R15_L70_1",
-        "DualDev_OneChanMonoSrc_16_2_Balanced_Reliability",
-        "SingleDev_OneChanStereoSrc_16_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability"
+        "Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability"
       ]
     },
     {
       "name": "Game",
       "configurations": [
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1",
+        "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Low_Latency",
+        "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
         "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_Balanced_Reliability_1",
         "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_TwoChanStereoSrc_16khz_30octs_R3_L12_1",
         "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_High_Reliability_1",
         "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_1",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
-        "DualDev_OneChanStereoSnk_48_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_48_3_Low_Latency",
-        "DualDev_OneChanStereoSnk_48_1_Low_Latency",
-        "DualDev_OneChanStereoSnk_32_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_32_1_Low_Latency",
-        "DualDev_OneChanStereoSnk_24_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_24_1_Low_Latency",
-        "DualDev_OneChanStereoSnk_16_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_16_1_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_48_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_48_3_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_48_1_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_32_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_32_1_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_24_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_24_1_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_16_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_16_1_Low_Latency",
-        "SingleDev_OneChanStereoSnk_48_2_Low_Latency",
-        "SingleDev_OneChanStereoSnk_48_3_Low_Latency",
-        "SingleDev_OneChanStereoSnk_48_1_Low_Latency",
-        "SingleDev_OneChanStereoSnk_32_2_Low_Latency",
-        "SingleDev_OneChanStereoSnk_32_1_Low_Latency",
-        "SingleDev_OneChanStereoSnk_24_2_Low_Latency",
-        "SingleDev_OneChanStereoSnk_24_1_Low_Latency",
-        "SingleDev_OneChanStereoSnk_16_2_Low_Latency",
-        "SingleDev_OneChanStereoSnk_16_1_Low_Latency"
+        "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+        "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_48_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_48_3_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_48_1_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_32_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_32_1_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_24_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_24_1_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_1_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_48_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_48_3_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_48_1_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_32_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_32_1_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_24_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_24_1_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_1_Low_Latency"
       ]
     },
     {
       "name": "VoiceAssistants",
       "configurations": [
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Balanced_Reliability",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Balanced_Reliability",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1",
-        "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2_Balanced_Reliability",
-        "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2_Balanced_Reliability",
-        "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2_Balanced_Reliability",
-        "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
-        "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
-        "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
-        "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
-        "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
-        "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
-        "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2_Balanced_Reliability",
-        "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2_Balanced_Reliability",
-        "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2_Balanced_Reliability",
-        "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
-        "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
-        "SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
-        "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
-        "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
-        "SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability"
+        "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1",
+        "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1",
+        "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_1",
+        "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Balanced_Reliability",
+        "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Balanced_Reliability",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_1",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_1",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_1",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
+        "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+        "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
+        "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
+        "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+        "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+        "Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+        "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+        "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+        "Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+        "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+        "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+        "One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+        "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+        "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+        "One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+        "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+        "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
+        "One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability"
       ]
     },
     {
@@ -260,44 +215,44 @@
       "configurations": [
         "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_Balanced_Reliability_1",
         "VND_SingleDev_TwoChanStereoSrc_48khz_100octs_R11_L40_1",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Balanced_Reliability",
-        "DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Balanced_Reliability",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
-        "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
-        "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
-        "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1",
-        "SingleDev_OneChanMonoSrc_48_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_48_1_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_32_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_32_1_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability",
-        "SingleDev_OneChanMonoSrc_16_1_Balanced_Reliability"
+        "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1",
+        "Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1",
+        "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_1",
+        "Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Balanced_Reliability",
+        "Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Balanced_Reliability",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_1",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_1",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_1",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
+        "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+        "Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
+        "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
+        "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
+        "One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
+        "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
+        "One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
+        "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
+        "One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
+        "One-OneChan-SrcAse-Lc3_48_2_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_48_1_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_32_1_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
+        "One-OneChan-SrcAse-Lc3_16_1_Balanced_Reliability"
       ]
     }
   ]
diff --git a/bluetooth/finder/aidl/vts/Android.bp b/bluetooth/finder/aidl/vts/Android.bp
index 6b0285e..29a0c0f 100644
--- a/bluetooth/finder/aidl/vts/Android.bp
+++ b/bluetooth/finder/aidl/vts/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_bluetooth",
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
@@ -31,7 +32,6 @@
     ],
     static_libs: [
         "android.hardware.bluetooth.finder-V1-ndk",
-        "libbluetooth-types",
     ],
     test_config: "VtsHalBluetoothFinderTargetTest.xml",
     test_suites: [
diff --git a/bluetooth/hci/h4_protocol.cc b/bluetooth/hci/h4_protocol.cc
index 5f6d86e..109ca5c 100644
--- a/bluetooth/hci/h4_protocol.cc
+++ b/bluetooth/hci/h4_protocol.cc
@@ -45,29 +45,50 @@
 }
 
 size_t H4Protocol::Send(PacketType type, const uint8_t* data, size_t length) {
-  /* For HCI communication over USB dongle, multiple write results in
-   * response timeout as driver expect type + data at once to process
-   * the command, so using "writev"(for atomicity) here.
-   */
-  struct iovec iov[2];
-  ssize_t ret = 0;
-  iov[0].iov_base = &type;
-  iov[0].iov_len = sizeof(type);
-  iov[1].iov_base = (void*)data;
-  iov[1].iov_len = length;
-  while (1) {
-    ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, 2));
+  struct iovec iov_array[] = {{&type, sizeof(type)},
+                              {const_cast<uint8_t*>(data), length}};
+  size_t iovcnt = sizeof(iov_array) / sizeof(iov_array[0]);
+  struct iovec* iov = iov_array;
+  size_t total_bytes = sizeof(type) + length;
+  size_t remaining_bytes = total_bytes;
+  size_t bytes_written = 0;
+
+  while (remaining_bytes > 0) {
+    ssize_t ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, iovcnt));
     if (ret == -1) {
-      LOG_ALWAYS_FATAL("%s error writing to UART (%s)", __func__,
-                       strerror(errno));
+      if (errno == EAGAIN) continue;
+      ALOGE("Error writing to UART (%s)", strerror(errno));
+      break;
     } else if (ret == 0) {
       // Nothing written :(
       ALOGE("%s zero bytes written - something went wrong...", __func__);
       break;
+    } else if (ret == remaining_bytes) {
+      // Everything written
+      bytes_written += ret;
+      break;
     }
-    break;
+
+    // Updating counters for partial writes
+    bytes_written += ret;
+    remaining_bytes -= ret;
+
+    ALOGW("%s: %zu/%zu bytes written - retrying remaining %zu bytes", __func__,
+          bytes_written, total_bytes, remaining_bytes);
+
+    // Remove fully written iovs from the list
+    while (ret >= iov->iov_len) {
+      ret -= iov->iov_len;
+      ++iov;
+      --iovcnt;
+    }
+    // Adjust the iov to point to the remaining data that needs to be written
+    if (ret > 0) {
+      iov->iov_base = static_cast<uint8_t*>(iov->iov_base) + ret;
+      iov->iov_len -= ret;
+    }
   }
-  return ret;
+  return total_bytes - remaining_bytes;
 }
 
 size_t H4Protocol::OnPacketReady(const std::vector<uint8_t>& packet) {
diff --git a/bluetooth/lmp_event/aidl/vts/Android.bp b/bluetooth/lmp_event/aidl/vts/Android.bp
index b89351e..a137434 100644
--- a/bluetooth/lmp_event/aidl/vts/Android.bp
+++ b/bluetooth/lmp_event/aidl/vts/Android.bp
@@ -1,5 +1,6 @@
 cc_test {
     name: "VtsHalLmpEventTargetTest",
+    team: "trendy_team_bluetooth",
     defaults: [
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
diff --git a/bluetooth/ranging/OWNERS b/bluetooth/ranging/OWNERS
index 3d95624..88a91ea 100644
--- a/bluetooth/ranging/OWNERS
+++ b/bluetooth/ranging/OWNERS
@@ -3,3 +3,4 @@
 include platform/packages/modules/Bluetooth:/OWNERS
 
 chienyuanhuang@google.com
+steveliu@google.com
diff --git a/bluetooth/ranging/aidl/Android.bp b/bluetooth/ranging/aidl/Android.bp
index d0d1b90..b5ae205 100644
--- a/bluetooth/ranging/aidl/Android.bp
+++ b/bluetooth/ranging/aidl/Android.bp
@@ -31,7 +31,7 @@
         ndk: {
             apex_available: [
                 "//apex_available:platform",
-                "com.android.btservices",
+                "com.android.bt",
             ],
             min_sdk_version: "33",
         },
@@ -42,6 +42,6 @@
             imports: [],
         },
     ],
-    frozen: true,
+    frozen: false,
 
 }
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/BluetoothChannelSoundingParameters.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/BluetoothChannelSoundingParameters.aidl
index e8fefbe..03a7d24 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/BluetoothChannelSoundingParameters.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/BluetoothChannelSoundingParameters.aidl
@@ -38,6 +38,9 @@
   int aclHandle;
   int l2capCid;
   int realTimeProcedureDataAttHandle;
+  /**
+   * @deprecated use the role in Config.aidl
+   */
   android.hardware.bluetooth.ranging.Role role;
   boolean localSupportsSoundingPhaseBasedRanging;
   boolean remoteSupportsSoundingPhaseBaseRanging;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/Ch3cShapeType.aidl
similarity index 91%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/Ch3cShapeType.aidl
index ca8b3eb..70bed88 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/Ch3cShapeType.aidl
@@ -31,8 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.bluetooth.ranging;
+@Backing(type="byte") @VintfStability
+enum Ch3cShapeType {
+  HAT_SHAPE = 0x00,
+  X_SHAPE = 0x01,
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSelectionType.aidl
similarity index 90%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSelectionType.aidl
index ea3a173..78bbbc1 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSelectionType.aidl
@@ -31,9 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.ranging;
+@Backing(type="byte") @VintfStability
+enum ChannelSelectionType {
+  ALOGRITHM_3B = 0x00,
+  ALOGRITHM_3C = 0x01,
 }
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
index 8fc77ae..64aabec 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
@@ -32,6 +32,9 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.bluetooth.ranging;
+/**
+ * @deprecated use ChannelSoundingProcedureData
+ */
 @VintfStability
 parcelable ChannelSoudingRawData {
   int procedureCounter;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingProcedureData.aidl
similarity index 70%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingProcedureData.aidl
index 5c26cc2..ef4facc 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingProcedureData.aidl
@@ -31,7 +31,16 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-interface IHwCryptoOperations {
-  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+package android.hardware.bluetooth.ranging;
+@VintfStability
+parcelable ChannelSoundingProcedureData {
+  int procedureCounter;
+  int procedureSequence;
+  byte initiatorSelectedTxPower = SELECTED_TX_POWER_UNAVAILABLE /* 127 */;
+  byte reflectorSelectedTxPower = SELECTED_TX_POWER_UNAVAILABLE /* 127 */;
+  android.hardware.bluetooth.ranging.SubeventResultData[] initiatorSubeventResultData;
+  android.hardware.bluetooth.ranging.ProcedureAbortReason initiatorProcedureAbortReason;
+  android.hardware.bluetooth.ranging.SubeventResultData[] reflectorSubeventResultData;
+  android.hardware.bluetooth.ranging.ProcedureAbortReason reflectorProcedureAbortReason;
+  const byte SELECTED_TX_POWER_UNAVAILABLE = 0x7Fu8;
 }
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
index 172ac5e..b86994e 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
@@ -32,6 +32,9 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.bluetooth.ranging;
+/**
+ * @deprecated use ChannelSoundingProcedureData
+ */
 @VintfStability
 parcelable ChannelSoundingSingleSideData {
   @nullable android.hardware.bluetooth.ranging.StepTonePct[] stepTonePcts;
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ComplexNumber.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ComplexNumber.aidl
index 4d5ac21..c3d5d91 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ComplexNumber.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ComplexNumber.aidl
@@ -32,6 +32,9 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.bluetooth.ranging;
+/**
+ * @deprecated use PctIQSample instead for V2 and above.
+ */
 @VintfStability
 parcelable ComplexNumber {
   double real;
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/Config.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/Config.aidl
index c9ac991..bd07cd0 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/Config.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/Config.aidl
@@ -38,4 +38,22 @@
   android.hardware.bluetooth.ranging.SubModeType subModeType;
   android.hardware.bluetooth.ranging.RttType rttType;
   byte[10] channelMap;
+  int minMainModeSteps;
+  int maxMainModeSteps;
+  byte mainModeRepetition;
+  byte mode0Steps;
+  android.hardware.bluetooth.ranging.Role role;
+  android.hardware.bluetooth.ranging.CsSyncPhyType csSyncPhyType;
+  android.hardware.bluetooth.ranging.ChannelSelectionType channelSelectionType;
+  android.hardware.bluetooth.ranging.Ch3cShapeType ch3cShapeType;
+  byte ch3cJump;
+  int channelMapRepetition;
+  int tIp1TimeUs;
+  int tIp2TimeUs;
+  int tFcsTimeUs;
+  byte tPmTimeUs;
+  byte tSwTimeUsSupportedByLocal;
+  byte tSwTimeUsSupportedByRemote;
+  int bleConnInterval = BLE_CONN_INTERVAL_UNAVAILABLE /* 0 */;
+  const int BLE_CONN_INTERVAL_UNAVAILABLE = 0;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/CsSyncPhyType.aidl
similarity index 89%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/CsSyncPhyType.aidl
index ea3a173..9611f13 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/CsSyncPhyType.aidl
@@ -31,9 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.ranging;
+@Backing(type="byte") @VintfStability
+enum CsSyncPhyType {
+  NOT_VALID_PHY = 0x00,
+  LE_1M_PHY = 0x01,
+  LE_2M_PHY = 0x02,
+  LE_2M_2BT_PHY = 0x03,
 }
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/IBluetoothChannelSounding.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/IBluetoothChannelSounding.aidl
index 004a482..19b949f 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/IBluetoothChannelSounding.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/IBluetoothChannelSounding.aidl
@@ -36,6 +36,10 @@
 interface IBluetoothChannelSounding {
   @nullable android.hardware.bluetooth.ranging.VendorSpecificData[] getVendorSpecificData();
   @nullable android.hardware.bluetooth.ranging.SessionType[] getSupportedSessionTypes();
+  /**
+   * @deprecated use getSupportedCsSecurityLevels() instead
+   */
   android.hardware.bluetooth.ranging.CsSecurityLevel getMaxSupportedCsSecurityLevel();
   @nullable android.hardware.bluetooth.ranging.IBluetoothChannelSoundingSession openSession(in android.hardware.bluetooth.ranging.BluetoothChannelSoundingParameters params, in android.hardware.bluetooth.ranging.IBluetoothChannelSoundingSessionCallback callback);
+  android.hardware.bluetooth.ranging.CsSecurityLevel[] getSupportedCsSecurityLevels();
 }
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/IBluetoothChannelSoundingSession.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/IBluetoothChannelSoundingSession.aidl
index 9f691b4..99418bc 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/IBluetoothChannelSoundingSession.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/IBluetoothChannelSoundingSession.aidl
@@ -39,4 +39,8 @@
   boolean isAbortedProcedureRequired();
   void writeRawData(in android.hardware.bluetooth.ranging.ChannelSoudingRawData rawData);
   void close(android.hardware.bluetooth.ranging.Reason reason);
+  void writeProcedureData(in android.hardware.bluetooth.ranging.ChannelSoundingProcedureData procedureData);
+  void updateChannelSoundingConfig(in android.hardware.bluetooth.ranging.Config conifg);
+  void updateProcedureEnableConfig(in android.hardware.bluetooth.ranging.ProcedureEnableConfig procedureEnableConfig);
+  void updateBleConnInterval(in int bleConnInterval);
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeData.aidl
similarity index 83%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeData.aidl
index ea3a173..6fdfffe 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeData.aidl
@@ -31,9 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.ranging;
+@VintfStability
+union ModeData {
+  android.hardware.bluetooth.ranging.ModeZeroData modeZeroData;
+  android.hardware.bluetooth.ranging.ModeOneData modeOneData;
+  android.hardware.bluetooth.ranging.ModeTwoData modeTwoData;
+  android.hardware.bluetooth.ranging.ModeThreeData modeThreeData;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeOneData.aidl
similarity index 68%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeOneData.aidl
index 5c26cc2..698dd63 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeOneData.aidl
@@ -31,7 +31,20 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-interface IHwCryptoOperations {
-  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+package android.hardware.bluetooth.ranging;
+@VintfStability
+parcelable ModeOneData {
+  byte packetQuality;
+  android.hardware.bluetooth.ranging.Nadm packetNadm;
+  byte packetRssiDbm = PACKET_RSSI_UNAVAILABLE /* 127 */;
+  android.hardware.bluetooth.ranging.RttToaTodData rttToaTodData;
+  byte packetAntenna;
+  @nullable android.hardware.bluetooth.ranging.PctIQSample packetPct1;
+  @nullable android.hardware.bluetooth.ranging.PctIQSample packetPct2;
+  const byte FLAG_CS_ACCESS_ADDR_SUCCESS = 0x0;
+  const byte FLAG_CS_ACCESS_ADDR_ERRORS = 0x1;
+  const byte FLAG_CS_ACCESS_ADDR_NOT_FOUND = 0x2;
+  const byte FLAG_CS_ACCESS_ADDR_MASK = 0xF;
+  const byte RANDOM_OR_SOUNDING_SEQUENCE_ERROR_COUNT_SHIFT = 4;
+  const byte PACKET_RSSI_UNAVAILABLE = 0x7Fu8;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeThreeData.aidl
similarity index 88%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeThreeData.aidl
index ea3a173..1aa928b 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeThreeData.aidl
@@ -31,9 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.ranging;
+@VintfStability
+parcelable ModeThreeData {
+  android.hardware.bluetooth.ranging.ModeOneData modeOneData;
+  android.hardware.bluetooth.ranging.ModeTwoData modeTwoData;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeTwoData.aidl
similarity index 74%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeTwoData.aidl
index ea3a173..c07b0c0 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeTwoData.aidl
@@ -31,9 +31,18 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.ranging;
+@VintfStability
+parcelable ModeTwoData {
+  byte antennaPermutationIndex;
+  android.hardware.bluetooth.ranging.PctIQSample[] tonePctIQSamples;
+  byte[] toneQualityIndicators;
+  const int TONE_QUALITY_HIGH = 0x0;
+  const int TONE_QUALITY_MEDIUM = 0x1;
+  const int TONE_QUALITY_LOW = 0x2;
+  const int TONE_QUALITY_UNAVAILABLE = 0x3;
+  const int EXTENSION_SLOT_NONE = 0x0;
+  const int EXTENSION_SLOT_TONE_NOT_EXPECTED_TO_BE_PRESENT = 0x1;
+  const int EXTENSION_SLOT_TONE_EXPECTED_TO_BE_PRESENT = 0x2;
+  const int EXTENSION_SLOT_SHIFT = 4;
 }
diff --git a/drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevel.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeZeroData.aidl
similarity index 70%
copy from drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevel.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeZeroData.aidl
index 5704fb0..f94f3d1 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevel.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ModeZeroData.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright 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.
@@ -31,15 +31,18 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.drm;
-@Backing(type="int") @VintfStability
-enum HdcpLevel {
-  HDCP_UNKNOWN = 0,
-  HDCP_NONE = 1,
-  HDCP_V1 = 2,
-  HDCP_V2 = 3,
-  HDCP_V2_1 = 4,
-  HDCP_V2_2 = 5,
-  HDCP_NO_OUTPUT = 6,
-  HDCP_V2_3 = 7,
+package android.hardware.bluetooth.ranging;
+@VintfStability
+parcelable ModeZeroData {
+  byte packetQuality;
+  byte packetRssiDbm = PACKET_RSSI_UNAVAILABLE /* 127 */;
+  byte packetAntenna;
+  int initiatorMeasuredFreqOffset = MEASURED_FREQ_OFFSET_UNAVAILABLE /* -16384 */;
+  const byte FLAG_CS_ACCESS_ADDR_SUCCESS = 0x0;
+  const byte FLAG_CS_ACCESS_ADDR_ERRORS = 0x1;
+  const byte FLAG_CS_ACCESS_ADDR_NOT_FOUND = 0x2;
+  const byte FLAG_CS_ACCESS_ADDR_MASK = 0xF;
+  const byte RANDOM_OR_SOUNDING_SEQUENCE_ERROR_COUNT_SHIFT = 4;
+  const byte PACKET_RSSI_UNAVAILABLE = 0x7Fu8;
+  const int MEASURED_FREQ_OFFSET_UNAVAILABLE = 0xFFFFC000;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/PctIQSample.aidl
similarity index 87%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/PctIQSample.aidl
index ea3a173..a15b579 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/PctIQSample.aidl
@@ -31,9 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.ranging;
+@VintfStability
+parcelable PctIQSample {
+  int iSample = SAMPLE_UNAVAILABLE /* -1 */;
+  int qSample = SAMPLE_UNAVAILABLE /* -1 */;
+  const int SAMPLE_UNAVAILABLE = 0xFFFFFFFF;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ProcedureAbortReason.aidl
similarity index 85%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ProcedureAbortReason.aidl
index d88d5c8..ead7ceb 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ProcedureAbortReason.aidl
@@ -31,12 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-parcelable MemoryBufferParameter {
-  android.hardware.security.see.hwcrypto.MemoryBufferParameter.MemoryBuffer bufferHandle;
-  int sizeBytes;
-  union MemoryBuffer {
-    ParcelFileDescriptor input;
-    ParcelFileDescriptor output;
-  }
+package android.hardware.bluetooth.ranging;
+@Backing(type="byte") @VintfStability
+enum ProcedureAbortReason {
+  SUCCESS = 0x0,
+  LOCAL_OR_REMOTE_REQUEST = 0x01,
+  FILTERED_CHANNEL_MAP_LESS_THAN_15 = 0x02,
+  CHANNEL_MAP_UPDATE_INSTANT_PASSED = 0x03,
+  UNSPECIFIED = 0x0F,
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ProcedureEnableConfig.aidl
similarity index 84%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ProcedureEnableConfig.aidl
index d88d5c8..11030bb 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ProcedureEnableConfig.aidl
@@ -31,12 +31,15 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-parcelable MemoryBufferParameter {
-  android.hardware.security.see.hwcrypto.MemoryBufferParameter.MemoryBuffer bufferHandle;
-  int sizeBytes;
-  union MemoryBuffer {
-    ParcelFileDescriptor input;
-    ParcelFileDescriptor output;
-  }
+package android.hardware.bluetooth.ranging;
+@VintfStability
+parcelable ProcedureEnableConfig {
+  byte toneAntennaConfigSelection;
+  int subeventLenUs;
+  byte subeventsPerEvent;
+  int subeventInterval;
+  int eventInterval;
+  int procedureInterval;
+  int procedureCount;
+  int maxProcedureLen;
 }
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/RangingResult.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/RangingResult.aidl
index d092b80..ccac70b 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/RangingResult.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/RangingResult.aidl
@@ -45,4 +45,6 @@
   android.hardware.bluetooth.ranging.Nadm detectedAttackLevel;
   double velocityMetersPerSecond;
   @nullable byte[] vendorSpecificCsRangingResultsData;
+  android.hardware.bluetooth.ranging.RangingResultStatus rangingResultStatus;
+  long timestampNanos;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/RangingResultStatus.aidl
similarity index 86%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/RangingResultStatus.aidl
index ea3a173..cdf8ed2 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/RangingResultStatus.aidl
@@ -31,9 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.ranging;
+@Backing(type="byte") @VintfStability
+enum RangingResultStatus {
+  SUCCESS = 0x00,
+  FAIL_INITIATOR_ABORT = 0x01,
+  FAIL_REFLECTOR_ABORT = 0x02,
+  FAIL_BOTH_ABORT = 0x03,
+  FAIL_UNSPECIFIED = 0xFFu8,
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/RttToaTodData.aidl
similarity index 86%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/RttToaTodData.aidl
index ea3a173..496ccb2 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/RttToaTodData.aidl
@@ -31,9 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.ranging;
+@VintfStability
+union RttToaTodData {
+  int toaTodInitiator = TOA_TOD_UNAVAILABLE /* -32768 */;
+  int todToaReflector = TOA_TOD_UNAVAILABLE /* -32768 */;
+  const int TOA_TOD_UNAVAILABLE = 0xFFFF8000;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationData.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepData.aidl
similarity index 88%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationData.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepData.aidl
index aad3ac1..cdebc8e 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationData.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepData.aidl
@@ -31,8 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-union OperationData {
-  android.hardware.security.see.hwcrypto.types.MemoryBufferReference memoryBufferReference;
-  byte[] dataBuffer;
+package android.hardware.bluetooth.ranging;
+@VintfStability
+parcelable StepData {
+  byte stepChannel;
+  android.hardware.bluetooth.ranging.ModeType stepMode;
+  android.hardware.bluetooth.ranging.ModeData stepModeData;
 }
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepTonePct.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepTonePct.aidl
index 4125748..02d5413 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepTonePct.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepTonePct.aidl
@@ -32,6 +32,9 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.bluetooth.ranging;
+/**
+ * @deprecated use ModeTwoData
+ */
 @VintfStability
 parcelable StepTonePct {
   List<android.hardware.bluetooth.ranging.ComplexNumber> tonePcts;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/SubeventAbortReason.aidl
similarity index 85%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/SubeventAbortReason.aidl
index d88d5c8..a3bb366 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/SubeventAbortReason.aidl
@@ -31,12 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-parcelable MemoryBufferParameter {
-  android.hardware.security.see.hwcrypto.MemoryBufferParameter.MemoryBuffer bufferHandle;
-  int sizeBytes;
-  union MemoryBuffer {
-    ParcelFileDescriptor input;
-    ParcelFileDescriptor output;
-  }
+package android.hardware.bluetooth.ranging;
+@Backing(type="byte") @VintfStability
+enum SubeventAbortReason {
+  SUCCESS = 0x0,
+  LOCAL_OR_REMOTE_REQUEST = 0x01,
+  NO_CS_SYNC_RECEIVED = 0x02,
+  SCHEDULING_CONFLICTS_OR_LIMITED_RESOURCES = 0x03,
+  UNSPECIFIED = 0x0F,
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/SubeventResultData.aidl
similarity index 77%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
copy to bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/SubeventResultData.aidl
index 5c26cc2..3a7c393 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/SubeventResultData.aidl
@@ -31,7 +31,15 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-interface IHwCryptoOperations {
-  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+package android.hardware.bluetooth.ranging;
+@VintfStability
+parcelable SubeventResultData {
+  int startAclConnEventCounter;
+  int frequencyCompensation = FREQ_COMPENSATION_UNAVAILABLE /* -16384 */;
+  byte referencePowerLevelDbm;
+  byte numAntennaPaths;
+  android.hardware.bluetooth.ranging.SubeventAbortReason subeventAbortReason;
+  android.hardware.bluetooth.ranging.StepData[] stepData;
+  long timestampNanos;
+  const int FREQ_COMPENSATION_UNAVAILABLE = 0xFFFFC000;
 }
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/BluetoothChannelSoundingParameters.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/BluetoothChannelSoundingParameters.aidl
index 0cda847..fbc0165 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/BluetoothChannelSoundingParameters.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/BluetoothChannelSoundingParameters.aidl
@@ -44,6 +44,7 @@
     int realTimeProcedureDataAttHandle;
     /**
      * Role of the local device.
+     * @deprecated use the role in Config.aidl
      */
     Role role;
     /**
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/Ch3cShapeType.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/Ch3cShapeType.aidl
new file mode 100644
index 0000000..558f68b
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/Ch3cShapeType.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+/**
+ * The selected shape to be rendered when Channel Selection Algorithm #3c is used
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.42 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+@Backing(type="byte")
+enum Ch3cShapeType {
+    /**
+     * Use Hat shape for user-specified channel sequence
+     */
+    HAT_SHAPE = 0x00,
+    /**
+     * Use X shape for user-specified channel sequence
+     */
+    X_SHAPE = 0x01,
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSelectionType.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSelectionType.aidl
new file mode 100644
index 0000000..6fd71aa
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSelectionType.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+/**
+ * The channel selection algorithm for non-mode-0 steps
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.42 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+@Backing(type="byte")
+enum ChannelSelectionType {
+    /**
+     * Use Channel Selection Algorithm #3b for non-mode-0 CS steps
+     */
+    ALOGRITHM_3B = 0x00,
+    /**
+     * Use Channel Selection Algorithm #3c for non-mode-0 CS steps
+     */
+    ALOGRITHM_3C = 0x01,
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
index 78ce4f4..f06af0f 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
@@ -24,6 +24,7 @@
  * See Channel Sounding CR_PR 3.1.10 and Channel Sounding HCI Updates CR_PR 3.1.23 for details.
  *
  * Specification: https://www.bluetooth.com/specifications/specs/channel-sounding-cr-pr/
+ * @deprecated use ChannelSoundingProcedureData
  */
 @VintfStability
 parcelable ChannelSoudingRawData {
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingProcedureData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingProcedureData.aidl
new file mode 100644
index 0000000..2c51abe
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingProcedureData.aidl
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+import android.hardware.bluetooth.ranging.ProcedureAbortReason;
+import android.hardware.bluetooth.ranging.SubeventResultData;
+
+/**
+ * The measured data for a whole procedure, it includes all local and remote related data.
+ */
+@VintfStability
+parcelable ChannelSoundingProcedureData {
+    /**
+     * CS procedure count since completion of the Channel Sounding Security Start procedure
+     */
+    int procedureCounter;
+    /**
+     * The procequre sequence since completion of the Channel Sounding Procecedure Enable procedure,
+     * this is not defined by spec, BT
+     */
+    int procedureSequence;
+    const byte SELECTED_TX_POWER_UNAVAILABLE = 0x7Fu8;
+    /**
+     * Transmit power level used for CS procedure of initiator.
+     * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.43
+     * ** HCI_LE_CS_Procedure_Enable_Complete#selected_tx_power
+     * See BLUETOOTH Ranging Service Version 1.0 3.2.1.2
+     * ** Ranging Header#Selected TX power
+     * Range: -127 to 20
+     * Unit: dBm
+     * value: 0x7F - Transmit power level is unavailable
+     */
+    byte initiatorSelectedTxPower = SELECTED_TX_POWER_UNAVAILABLE;
+    /**
+     * Transmit power level used for CS procedure of reflector.
+     * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.43
+     * ** HCI_LE_CS_Procedure_Enable_Complete#selected_tx_power
+     * See BLUETOOTH Ranging Service Version 1.0 3.2.1.2
+     * ** Ranging Header#Selected TX power
+     * Range: -127 to 20
+     * Unit: dBm
+     * value: 0x7F - Transmit power level is unavailable
+     */
+    byte reflectorSelectedTxPower = SELECTED_TX_POWER_UNAVAILABLE;
+    /**
+     * The subevent result data of initiator
+     */
+    SubeventResultData[] initiatorSubeventResultData;
+    /**
+     * Indicates the procedure abort reason of the initiator
+     */
+    ProcedureAbortReason initiatorProcedureAbortReason;
+    /**
+     * The subevent result data of reflector
+     */
+    SubeventResultData[] reflectorSubeventResultData;
+    /**
+     * Indicates the procedure abort reason of the initiator
+     */
+    ProcedureAbortReason reflectorProcedureAbortReason;
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
index 9c4b472..75f0b67 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
@@ -25,6 +25,7 @@
  * See Channel Sounding CR_PR 3.1.10 and Channel Sounding HCI Updates CR_PR 3.1.23 for details.
  *
  * Specification: https://www.bluetooth.com/specifications/specs/channel-sounding-cr-pr/
+ * @deprecated use ChannelSoundingProcedureData
  */
 @VintfStability
 parcelable ChannelSoundingSingleSideData {
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ComplexNumber.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ComplexNumber.aidl
index 5253d9f..8d59934 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ComplexNumber.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ComplexNumber.aidl
@@ -16,6 +16,9 @@
 
 package android.hardware.bluetooth.ranging;
 
+/**
+ * @deprecated use PctIQSample instead for V2 and above.
+ */
 @VintfStability
 parcelable ComplexNumber {
     double real;
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/Config.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/Config.aidl
index 85ae4c1..95817b5 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/Config.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/Config.aidl
@@ -16,10 +16,20 @@
 
 package android.hardware.bluetooth.ranging;
 
+import android.hardware.bluetooth.ranging.Ch3cShapeType;
+import android.hardware.bluetooth.ranging.ChannelSelectionType;
+import android.hardware.bluetooth.ranging.CsSyncPhyType;
 import android.hardware.bluetooth.ranging.ModeType;
+import android.hardware.bluetooth.ranging.Role;
 import android.hardware.bluetooth.ranging.RttType;
 import android.hardware.bluetooth.ranging.SubModeType;
 
+/**
+ * LE CS Config Complete data of Channel Sounding.
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.8.137 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
 @VintfStability
 parcelable Config {
     /**
@@ -42,4 +52,96 @@
      * Channel n is disabled for CS procedure = 0
      */
     byte[10] channelMap;
+    /**
+     * Minimum number of CS main mode steps to be executed before a submode step is executed
+     * Value: 0x02 to 0xFF
+     */
+    int minMainModeSteps;
+    /**
+     * Maximum number of CS main mode steps to be executed before a submode step is executed
+     * Value: 0x02 to 0xFF
+     */
+    int maxMainModeSteps;
+    /**
+     * Number of main mode steps taken from the end of the last CS subevent to be repeated at
+     * the beginning of the current CS subevent directly after the last mode-0 step of that event
+     * Value: 0x00 to 0x03
+     */
+    byte mainModeRepetition;
+    /**
+     * Number of CS mode-0 steps to be included at the beginning of each CS subevent
+     * Value: 0x00 to 0x03
+     */
+    byte mode0Steps;
+    /**
+     * The Channel Sounding role of the local device
+     */
+    Role role;
+    /**
+     * Indicates the PHY to be used for CS_SYNC exchanges during the CS procedure
+     */
+    CsSyncPhyType csSyncPhyType;
+    /**
+     * Indicates the Channel Selection Algorithm to be used during the CS procedure for non-mode-0
+     * steps
+     */
+    ChannelSelectionType channelSelectionType;
+    /**
+     * Indicates the selected shape
+     */
+    Ch3cShapeType ch3cShapeType;
+    /**
+     * Number of channels skipped in each rising and falling sequence
+     * Value: 0x02 to 0x08
+     */
+    byte ch3cJump;
+    /**
+     * The number of times the map represented by the Channel_Map field is to be cycled through
+     * for non-mode-0 steps within a CS procedure
+     * Value: 0x01 to 0xFF
+     */
+    int channelMapRepetition;
+    /**
+     * Interlude time in microseconds between the RTT packets
+     * Value: 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x50, or 0x91
+     * unit: us
+     */
+    int tIp1TimeUs;
+    /**
+     * Interlude time in microseconds between the CS tones
+     * Value: 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x50, or 0x91
+     * unit: us
+     */
+    int tIp2TimeUs;
+    /**
+     * Time in microseconds for frequency changes
+     * Value: 0x0F, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x50, 0x64, 0x78, or 0x96
+     * unit: us
+     */
+    int tFcsTimeUs;
+    /**
+     * Time in microseconds for the phase measurement period of the CS tones
+     * Value: 0x0A, 0x14, or 0x28
+     * unit: us
+     */
+    byte tPmTimeUs;
+    /**
+     * Time in microseconds for the antenna switch period of the CS tones supported by local device
+     * Value: 0, 1, 2, 4, 10 us
+     * see BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.8.130
+     */
+    byte tSwTimeUsSupportedByLocal;
+    /**
+     * Time in microseconds for the antenna switch period of the CS tones supported by remote device
+     * Value: 0, 1, 2, 4, 10 us
+     * see BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.39
+     */
+    byte tSwTimeUsSupportedByRemote;
+    const int BLE_CONN_INTERVAL_UNAVAILABLE = 0;
+    /**
+     * BLE event connection interval, a multiple of 1.25 ms in the range 7.5 ms to 4.0 s
+     * see BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 6, Part B 4.5.1
+     * Unit: 1.25ms
+     */
+    int bleConnInterval = BLE_CONN_INTERVAL_UNAVAILABLE;
 }
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/CsSyncPhyType.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/CsSyncPhyType.aidl
new file mode 100644
index 0000000..c7fe8a6
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/CsSyncPhyType.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+/**
+ * The PHY to be used for CS_SYNC exchanges during the CS procedure
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.42 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+@Backing(type="byte")
+enum CsSyncPhyType {
+    NOT_VALID_PHY = 0x00,
+    LE_1M_PHY = 0x01,
+    LE_2M_PHY = 0x02,
+    LE_2M_2BT_PHY = 0x03,
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/IBluetoothChannelSounding.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/IBluetoothChannelSounding.aidl
index 45ec79f..283f588 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/IBluetoothChannelSounding.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/IBluetoothChannelSounding.aidl
@@ -52,6 +52,7 @@
      *
      * @return CsSecurityLevel that indicates max supported security level of CS for ranging
      *         algorithms.
+     * @deprecated use getSupportedCsSecurityLevels() instead
      */
     CsSecurityLevel getMaxSupportedCsSecurityLevel();
 
@@ -63,4 +64,13 @@
     @nullable IBluetoothChannelSoundingSession openSession(
             in BluetoothChannelSoundingParameters params,
             in IBluetoothChannelSoundingSessionCallback callback);
+
+    /**
+     * API to get all supported security level (0 to 4) of CS for ranging algorithms.
+     *
+     *  See: BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 3, Part C 10.11.1
+     *
+     * @return All supported security level of CS for ranging algorithms.
+     */
+    CsSecurityLevel[] getSupportedCsSecurityLevels();
 }
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/IBluetoothChannelSoundingSession.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/IBluetoothChannelSoundingSession.aidl
index 97b147e..b87024e 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/IBluetoothChannelSoundingSession.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/IBluetoothChannelSoundingSession.aidl
@@ -17,6 +17,9 @@
 package android.hardware.bluetooth.ranging;
 
 import android.hardware.bluetooth.ranging.ChannelSoudingRawData;
+import android.hardware.bluetooth.ranging.ChannelSoundingProcedureData;
+import android.hardware.bluetooth.ranging.Config;
+import android.hardware.bluetooth.ranging.ProcedureEnableConfig;
 import android.hardware.bluetooth.ranging.Reason;
 import android.hardware.bluetooth.ranging.ResultType;
 import android.hardware.bluetooth.ranging.VendorSpecificData;
@@ -63,4 +66,28 @@
      * Close the current session. Object is no longer useful after this method.
      */
     void close(Reason reason);
+
+    /**
+     * API to provide raw ranging procedure data to the HAL. The HAL converts this data into
+     * meaningful ranging results using a proprietary algorithm and then calls back to the
+     * Bluetooth stack via BluetoothChannelSoundingSessionCallback.onResult().
+     */
+    void writeProcedureData(in ChannelSoundingProcedureData procedureData);
+
+    /**
+     * API to provide the latest CS config to the HAL.
+     */
+    void updateChannelSoundingConfig(in Config conifg);
+
+    /**
+     * API to provide the latest CS procedure enable complete information.
+     */
+    void updateProcedureEnableConfig(in ProcedureEnableConfig procedureEnableConfig);
+
+    /**
+     * API to provide the latest BLE event connection interval.
+     * BLE event connection interval, a multiple of 1.25 ms in the range 7.5 ms to 4.0 s
+     * see BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 6, Part B 4.5.1
+     */
+    void updateBleConnInterval(in int bleConnInterval);
 }
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeData.aidl
new file mode 100644
index 0000000..99199d2
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeData.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+import android.hardware.bluetooth.ranging.ModeOneData;
+import android.hardware.bluetooth.ranging.ModeThreeData;
+import android.hardware.bluetooth.ranging.ModeTwoData;
+import android.hardware.bluetooth.ranging.ModeZeroData;
+
+/**
+ * Mode specific data for a CS step of Channel Sounding.
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.44 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+union ModeData {
+    ModeZeroData modeZeroData;
+    ModeOneData modeOneData;
+    ModeTwoData modeTwoData;
+    ModeThreeData modeThreeData;
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeOneData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeOneData.aidl
new file mode 100644
index 0000000..51e8c70
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeOneData.aidl
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+import android.hardware.bluetooth.ranging.Nadm;
+import android.hardware.bluetooth.ranging.PctIQSample;
+import android.hardware.bluetooth.ranging.RttToaTodData;
+
+/**
+ * Mode 1 data for a CS step of Channel Sounding.
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.44 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+parcelable ModeOneData {
+    const byte FLAG_CS_ACCESS_ADDR_SUCCESS = 0x0;
+    const byte FLAG_CS_ACCESS_ADDR_ERRORS = 0x1;
+    const byte FLAG_CS_ACCESS_ADDR_NOT_FOUND = 0x2;
+    const byte FLAG_CS_ACCESS_ADDR_MASK = 0xF; // bit 3 is reserved
+    const byte RANDOM_OR_SOUNDING_SEQUENCE_ERROR_COUNT_SHIFT = 4;
+    /**
+     * bits 0 to 3:
+     * ** 0x0 = CS Access Address check is successful, and all bits match the expected sequence
+     * ** 0x1 = CS Access Address check contains one or more bit errors
+     * ** 0x2 = CS Access Address not found
+     * bits 4 to 7: Number of bit errors being reported on the payload with a random or sounding
+     * sequence. Value 0 may indicate zero bit errors or no report available.
+     * Value 15 may indicate 15 or more bit errors.
+     */
+    byte packetQuality;
+    /**
+     * Normalized Attack Detector Metric.
+     */
+    Nadm packetNadm;
+    const byte PACKET_RSSI_UNAVAILABLE = 0x7Fu8;
+    /**
+     * Range: -127 to +20
+     * Unit: dBm
+     * Value: 0x7F - RSSI is not available
+     */
+    byte packetRssiDbm = PACKET_RSSI_UNAVAILABLE;
+    /**
+     * Time difference of the time of arrival and the time of depature of the CS packets.
+     * see RttToaTodData for details.
+     */
+    RttToaTodData rttToaTodData;
+    /**
+     * Antenna identifier used for the RTT packet
+     * Value: 0x01 to 0x04
+     */
+    byte packetAntenna;
+    /**
+     * Phase Correction Term 1 of the sounding sequence.
+     */
+    @nullable PctIQSample packetPct1;
+    /**
+     * Phase Correction Term 2 of the sounding sequence.
+     */
+    @nullable PctIQSample packetPct2;
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeThreeData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeThreeData.aidl
new file mode 100644
index 0000000..a70d371
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeThreeData.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+import android.hardware.bluetooth.ranging.ModeOneData;
+import android.hardware.bluetooth.ranging.ModeTwoData;
+
+/**
+ * Mode 3 data for a CS step of Channel Sounding.
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.44 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+parcelable ModeThreeData {
+    ModeOneData modeOneData;
+    ModeTwoData modeTwoData;
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeTwoData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeTwoData.aidl
new file mode 100644
index 0000000..b360c90
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeTwoData.aidl
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+import android.hardware.bluetooth.ranging.PctIQSample;
+
+/**
+ * Mode 2 data for a CS step of Channel Sounding.
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.44 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+parcelable ModeTwoData {
+    /**
+     * Antenna Permutation Index for the chosen Num_Antenna_Paths parameter used during the
+     * phase measurement stage of the CS step
+     */
+    byte antennaPermutationIndex;
+    /**
+     * The I and Q sample of Phase Correction Term for (Num_Antenna_Paths + 1) CS tone
+     * The order is the same as the BT core defined
+     */
+    PctIQSample[] tonePctIQSamples;
+
+    const int TONE_QUALITY_HIGH = 0x0;
+    const int TONE_QUALITY_MEDIUM = 0x1;
+    const int TONE_QUALITY_LOW = 0x2;
+    const int TONE_QUALITY_UNAVAILABLE = 0x3;
+    const int EXTENSION_SLOT_NONE = 0x0;
+    const int EXTENSION_SLOT_TONE_NOT_EXPECTED_TO_BE_PRESENT = 0x1;
+    const int EXTENSION_SLOT_TONE_EXPECTED_TO_BE_PRESENT = 0x2;
+    /**
+     * Shift amount for extension slot (bits 4 to 7).
+     */
+    const int EXTENSION_SLOT_SHIFT = 4;
+    /**
+     * Tone quality indicator for (Num_Antenna_Paths + 1) CS tone
+     * bits 0 to 3:
+     * ** 0x0 = Tone quality is high
+     * ** 0x1 = Tone quality is medium
+     * ** 0x2 = Tone quality is low
+     * ** 0x3 = Tone quality is unavailable
+     * bits 4 to 7:
+     * ** 0x0 = Not tone extension slot
+     * ** 0x1 = Tone extension slot; tone not expected to be present
+     * ** 0x2 = Tone extension slot; tone expected to be present
+     */
+    byte[] toneQualityIndicators;
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeZeroData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeZeroData.aidl
new file mode 100644
index 0000000..6f326d1
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ModeZeroData.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+/**
+ * Mode 0 data for a CS step of Channel Sounding.
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.44 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+parcelable ModeZeroData {
+    const byte FLAG_CS_ACCESS_ADDR_SUCCESS = 0x0;
+    const byte FLAG_CS_ACCESS_ADDR_ERRORS = 0x1;
+    const byte FLAG_CS_ACCESS_ADDR_NOT_FOUND = 0x2;
+    const byte FLAG_CS_ACCESS_ADDR_MASK = 0xF; // bit 3 is reserved
+    const byte RANDOM_OR_SOUNDING_SEQUENCE_ERROR_COUNT_SHIFT = 4;
+    /**
+     * bits 0 to 3:
+     * ** 0x0 = CS Access Address check is successful, and all bits match the expected sequence
+     * ** 0x1 = CS Access Address check contains one or more bit errors
+     * ** 0x2 = CS Access Address not found
+     * bits 4 to 7: Number of bit errors being reported on the payload with a random or sounding
+     * sequence. Value 0 may indicate zero bit errors or no report available.
+     * Value 15 may indicate 15 or more bit errors.
+     */
+    byte packetQuality;
+    const byte PACKET_RSSI_UNAVAILABLE = 0x7Fu8;
+    /**
+     * Range: -127 to +20
+     * Unit: dBm
+     * Value: 0x7F - RSSI is not available
+     */
+    byte packetRssiDbm = PACKET_RSSI_UNAVAILABLE;
+    /**
+     * Antenna identifier used for the RTT packet
+     * Value: 0x01 to 0x04
+     */
+    byte packetAntenna;
+    const int MEASURED_FREQ_OFFSET_UNAVAILABLE = 0xFFFFC000;
+    /**
+     * Measured frequency offset in units of 0.01 ppm (15-bit signed integer, it had been converted
+     * as int here.) for initiator, this should be ignored for relector.
+     * Range: -100 ppm (0x58F0) to +100 ppm (0x2710)
+     * Unit: 0.01 ppm
+     * Value: 0xFFFFC000 - Frequency offset is not available
+     */
+    int initiatorMeasuredFreqOffset = MEASURED_FREQ_OFFSET_UNAVAILABLE;
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/PctIQSample.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/PctIQSample.aidl
new file mode 100644
index 0000000..81da870
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/PctIQSample.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+/**
+ * I and Q sample data of PCT.
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.44 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ *
+ * BT core defines the I and Q sample as following, they were converted to 2 integers here.
+ * ** bits 0 to 11 are the I sample with type sint12
+ * ** bits 12 to 23 are the Q sample with type sint12
+ */
+@VintfStability
+parcelable PctIQSample {
+    const int SAMPLE_UNAVAILABLE = 0xFFFFFFFF;
+
+    int iSample = SAMPLE_UNAVAILABLE;
+    int qSample = SAMPLE_UNAVAILABLE;
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ProcedureAbortReason.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ProcedureAbortReason.aidl
new file mode 100644
index 0000000..e8b520a
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ProcedureAbortReason.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+/**
+ * Procedure abort reason of Channel Sounding.
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.42 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+@Backing(type="byte")
+enum ProcedureAbortReason {
+    SUCCESS = 0x0,
+    LOCAL_OR_REMOTE_REQUEST = 0x01,
+    FILTERED_CHANNEL_MAP_LESS_THAN_15 = 0x02,
+    CHANNEL_MAP_UPDATE_INSTANT_PASSED = 0x03,
+    UNSPECIFIED = 0x0F,
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ProcedureEnableConfig.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ProcedureEnableConfig.aidl
new file mode 100644
index 0000000..b97f394
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ProcedureEnableConfig.aidl
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+/**
+ * LE CS Procedure Enable Complete data
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.43 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+parcelable ProcedureEnableConfig {
+    /**
+     * Antenna Configuration Index as described in [Vol 6] Part A, Section 5.3
+     * Value: 0x00 to 0x07
+     */
+    byte toneAntennaConfigSelection;
+    /**
+     * Duration for each CS subevent in microseconds
+     * Value: 1250 μs to 4 s
+     */
+    int subeventLenUs;
+    /**
+     * Number of CS subevents anchored off the same ACL connection event
+     * Value: 0x01 to 0x20
+     */
+    byte subeventsPerEvent;
+    /**
+     * Time between consecutive CS subevents anchored off the same ACL connection event.
+     * Unit: 0.625 ms
+     */
+    int subeventInterval;
+    /**
+     * Number of ACL connection events between consecutive CS event anchor points
+     */
+    int eventInterval;
+    /**
+     * Number of ACL connection events between consecutive CS procedure anchor points
+     */
+    int procedureInterval;
+    /**
+     * Number of CS procedures to be scheduled.
+     * Value: 0x0000 to 0xFFFF
+     * Value 0: CS procedures to continue until disabled
+     */
+    int procedureCount;
+    /**
+     * Maximum duration for each CS procedure
+     * Range: 0x0001 to 0xFFFF
+     * unit: 0.625 ms
+     * Time range: 0.625 ms to 40.959375 s
+     */
+    int maxProcedureLen;
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/RangingResult.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/RangingResult.aidl
index 65907dd..0962527 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/RangingResult.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/RangingResult.aidl
@@ -17,6 +17,7 @@
 package android.hardware.bluetooth.ranging;
 
 import android.hardware.bluetooth.ranging.Nadm;
+import android.hardware.bluetooth.ranging.RangingResultStatus;
 
 /**
  * Generic structure to return the ranging result
@@ -90,4 +91,13 @@
      * Parameter for vendors to place vendor-specific ranging results data.
      */
     @nullable byte[] vendorSpecificCsRangingResultsData;
+    /**
+     * If the result is valid, for e.g. the result was gotten from an aborted procedure.
+     */
+    RangingResultStatus rangingResultStatus;
+    /**
+     * The timestamp of the first subevent with the measured procedure.
+     * see SubeventResultData#timestampNanos
+     */
+    long timestampNanos;
 }
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/RangingResultStatus.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/RangingResultStatus.aidl
new file mode 100644
index 0000000..b877af8
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/RangingResultStatus.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+@VintfStability
+@Backing(type="byte")
+enum RangingResultStatus {
+    SUCCESS = 0x00,
+    /**
+     * The procedure of the initiator was aborted
+     */
+    FAIL_INITIATOR_ABORT = 0x01,
+    /**
+     * The procedure of the reflector was aborted
+     */
+    FAIL_REFLECTOR_ABORT = 0x02,
+    /**
+     * The procedure of both the initiator and the reflector were aborted
+     */
+    FAIL_BOTH_ABORT = 0x03,
+    FAIL_UNSPECIFIED = 0xFFu8,
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/RttToaTodData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/RttToaTodData.aidl
new file mode 100644
index 0000000..c2a48e4
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/RttToaTodData.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+/**
+ * The ToA/ToD data for the initator or reflector.
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.44 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+union RttToaTodData {
+    const int TOA_TOD_UNAVAILABLE = 0xFFFF8000;
+    /**
+     * Time difference in units of 0.5 nanoseconds between the time of arrival and
+     * the time of departure of the CS packets at the initiator during a CS step
+     * (16-bit signed integer, it had been converted to 'int' here), where the known
+     * nominal offsets are excluded.
+     * value: 0xFFFF8000 (0x8000 as signed 16-bit) - Time difference is not available
+     */
+    int toaTodInitiator = TOA_TOD_UNAVAILABLE;
+    /**
+     * Time difference in units of 0.5 nanoseconds between the time of departure
+     * and the time of arrival of the CS packets at the reflector during a CS step
+     * (16-bit signed integer,  it had been converted to 'int' here), where the known
+     * nominal offsets are excluded.
+     * value: 0xFFFF8000 (0x8000 as signed 16-bit) - Time difference is not available
+     */
+    int todToaReflector = TOA_TOD_UNAVAILABLE;
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepData.aidl
new file mode 100644
index 0000000..4006415
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepData.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+import android.hardware.bluetooth.ranging.ModeData;
+import android.hardware.bluetooth.ranging.ModeType;
+
+/**
+ * The data for a CS step of Channel Sounding.
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.44 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+parcelable StepData {
+    /**
+     * CS channel index
+     * Value: 0x00 to 0x4E
+     */
+    byte stepChannel;
+    ModeType stepMode;
+    ModeData stepModeData;
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepTonePct.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepTonePct.aidl
index 4650861..af25a11 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepTonePct.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepTonePct.aidl
@@ -20,6 +20,7 @@
 
 /**
  * Tone PCT data with quality indicator from a mode-2 or mode-3 step.
+ * @deprecated use ModeTwoData
  */
 @VintfStability
 parcelable StepTonePct {
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/SubeventAbortReason.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/SubeventAbortReason.aidl
new file mode 100644
index 0000000..bef87e8
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/SubeventAbortReason.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+/**
+ * The subevent abort reason of Channel Sounding.
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.42 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+@Backing(type="byte")
+enum SubeventAbortReason {
+    SUCCESS = 0x0,
+    LOCAL_OR_REMOTE_REQUEST = 0x01,
+    NO_CS_SYNC_RECEIVED = 0x02,
+    SCHEDULING_CONFLICTS_OR_LIMITED_RESOURCES = 0x03,
+    UNSPECIFIED = 0x0F,
+}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/SubeventResultData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/SubeventResultData.aidl
new file mode 100644
index 0000000..102d217
--- /dev/null
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/SubeventResultData.aidl
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.ranging;
+
+import android.hardware.bluetooth.ranging.StepData;
+import android.hardware.bluetooth.ranging.SubeventAbortReason;
+
+/**
+ * The subevent data within a CS procedure of Channel Sounding.
+ * See BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 4, Part E 7.7.65.44 for details.
+ *
+ * Specification: https://www.bluetooth.com/specifications/specs/core60-html/
+ */
+@VintfStability
+parcelable SubeventResultData {
+    /**
+     * Starting ACL connection event counter for the results reported in the event
+     */
+    int startAclConnEventCounter;
+    const int FREQ_COMPENSATION_UNAVAILABLE = 0xFFFFC000;
+    /**
+     * Frequency compensation value in units of 0.01 ppm (15-bit signed integer, it had been
+     * converted as int here.)
+     * Unit: 0.01 ppm
+     * 0xFFFFC000 - Frequency compensation value is not available, or the role is not initiator
+     */
+    int frequencyCompensation = FREQ_COMPENSATION_UNAVAILABLE;
+    /**
+     * Reference power level
+     * Range: -127 to 20
+     * Unit: dBm
+     */
+    byte referencePowerLevelDbm;
+    /**
+     * 0x00 Ignored because phase measurement does not occur during the CS step
+     * 0x01 to 0x04 Number of antenna paths used during the phase measurement stage of the CS step
+     */
+    byte numAntennaPaths;
+    /**
+     * Indicates the abort reason
+     */
+    SubeventAbortReason subeventAbortReason;
+    /**
+     * The measured data for all steps
+     */
+    StepData[] stepData;
+    /**
+     * Timestamp when all subevent data are received by the host; Not defined by the spec.
+     * Using epoch time in nano seconds (e.g., 1697673127175).
+     */
+    long timestampNanos;
+}
diff --git a/bluetooth/ranging/aidl/default/Android.bp b/bluetooth/ranging/aidl/default/Android.bp
index 5072a43..0912a4f 100644
--- a/bluetooth/ranging/aidl/default/Android.bp
+++ b/bluetooth/ranging/aidl/default/Android.bp
@@ -14,7 +14,7 @@
         "service.cpp",
     ],
     shared_libs: [
-        "android.hardware.bluetooth.ranging-V1-ndk",
+        "android.hardware.bluetooth.ranging-V2-ndk",
         "libbase",
         "libbinder_ndk",
         "libhidlbase",
diff --git a/bluetooth/ranging/aidl/default/BluetoothChannelSounding.cpp b/bluetooth/ranging/aidl/default/BluetoothChannelSounding.cpp
index 3807d4f..e2a8693 100644
--- a/bluetooth/ranging/aidl/default/BluetoothChannelSounding.cpp
+++ b/bluetooth/ranging/aidl/default/BluetoothChannelSounding.cpp
@@ -55,4 +55,11 @@
   *_aidl_return = session;
   return ::ndk::ScopedAStatus::ok();
 }
+
+ndk::ScopedAStatus BluetoothChannelSounding::getSupportedCsSecurityLevels(
+    std::vector<CsSecurityLevel>* _aidl_return) {
+  std::vector<CsSecurityLevel> supported_security_levels = {};
+  *_aidl_return = supported_security_levels;
+  return ::ndk::ScopedAStatus::ok();
+}
 }  // namespace aidl::android::hardware::bluetooth::ranging::impl
diff --git a/bluetooth/ranging/aidl/default/BluetoothChannelSounding.h b/bluetooth/ranging/aidl/default/BluetoothChannelSounding.h
index d6b5c03..43232fa 100644
--- a/bluetooth/ranging/aidl/default/BluetoothChannelSounding.h
+++ b/bluetooth/ranging/aidl/default/BluetoothChannelSounding.h
@@ -47,6 +47,8 @@
       const std::shared_ptr<IBluetoothChannelSoundingSessionCallback>&
           in_callback,
       std::shared_ptr<IBluetoothChannelSoundingSession>* _aidl_return) override;
+  ndk::ScopedAStatus getSupportedCsSecurityLevels(
+      std::vector<CsSecurityLevel>* _aidl_return) override;
 };
 
 }  // namespace aidl::android::hardware::bluetooth::ranging::impl
diff --git a/bluetooth/ranging/aidl/default/BluetoothChannelSoundingSession.cpp b/bluetooth/ranging/aidl/default/BluetoothChannelSoundingSession.cpp
index 6c58a07..bfdd5b6 100644
--- a/bluetooth/ranging/aidl/default/BluetoothChannelSoundingSession.cpp
+++ b/bluetooth/ranging/aidl/default/BluetoothChannelSoundingSession.cpp
@@ -52,4 +52,20 @@
   callback_->onClose(in_reason);
   return ::ndk::ScopedAStatus::ok();
 }
+ndk::ScopedAStatus BluetoothChannelSoundingSession::writeProcedureData(
+    const ChannelSoundingProcedureData& /*in_procedureData*/) {
+  return ::ndk::ScopedAStatus::ok();
+}
+ndk::ScopedAStatus BluetoothChannelSoundingSession::updateChannelSoundingConfig(
+    const Config& /*in_config*/) {
+  return ::ndk::ScopedAStatus::ok();
+}
+ndk::ScopedAStatus BluetoothChannelSoundingSession::updateProcedureEnableConfig(
+    const ProcedureEnableConfig& /*in_procedureEnableConfig*/) {
+  return ::ndk::ScopedAStatus::ok();
+}
+ndk::ScopedAStatus BluetoothChannelSoundingSession::updateBleConnInterval(
+    int /*in_bleConnInterval*/) {
+  return ::ndk::ScopedAStatus::ok();
+}
 }  // namespace aidl::android::hardware::bluetooth::ranging::impl
diff --git a/bluetooth/ranging/aidl/default/BluetoothChannelSoundingSession.h b/bluetooth/ranging/aidl/default/BluetoothChannelSoundingSession.h
index 6703f7f..ae66c7c 100644
--- a/bluetooth/ranging/aidl/default/BluetoothChannelSoundingSession.h
+++ b/bluetooth/ranging/aidl/default/BluetoothChannelSoundingSession.h
@@ -22,6 +22,10 @@
 namespace aidl::android::hardware::bluetooth::ranging::impl {
 
 using ::aidl::android::hardware::bluetooth::ranging::ChannelSoudingRawData;
+using ::aidl::android::hardware::bluetooth::ranging::
+    ChannelSoundingProcedureData;
+using ::aidl::android::hardware::bluetooth::ranging::Config;
+using ::aidl::android::hardware::bluetooth::ranging::ProcedureEnableConfig;
 using ::aidl::android::hardware::bluetooth::ranging::Reason;
 using ::aidl::android::hardware::bluetooth::ranging::ResultType;
 using ::aidl::android::hardware::bluetooth::ranging::VendorSpecificData;
@@ -42,6 +46,13 @@
   ndk::ScopedAStatus writeRawData(
       const ChannelSoudingRawData& in_rawData) override;
   ndk::ScopedAStatus close(Reason in_reason) override;
+  ndk::ScopedAStatus writeProcedureData(
+      const ChannelSoundingProcedureData& in_procedureData) override;
+  ndk::ScopedAStatus updateChannelSoundingConfig(
+      const Config& in_config) override;
+  ndk::ScopedAStatus updateProcedureEnableConfig(
+      const ProcedureEnableConfig& in_procedureEnableConfig) override;
+  ndk::ScopedAStatus updateBleConnInterval(int in_bleConnInterval) override;
 
  private:
   std::shared_ptr<IBluetoothChannelSoundingSessionCallback> callback_;
diff --git a/bluetooth/ranging/aidl/default/bluetooth-ranging-service-default.xml b/bluetooth/ranging/aidl/default/bluetooth-ranging-service-default.xml
index fe3613d..87adf2c 100644
--- a/bluetooth/ranging/aidl/default/bluetooth-ranging-service-default.xml
+++ b/bluetooth/ranging/aidl/default/bluetooth-ranging-service-default.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.bluetooth.ranging</name>
-        <version>1</version>
+        <version>2</version>
         <fqname>IBluetoothChannelSounding/default</fqname>
     </hal>
 </manifest>
diff --git a/bluetooth/ranging/aidl/vts/Android.bp b/bluetooth/ranging/aidl/vts/Android.bp
index ead9992..7f6ceff 100644
--- a/bluetooth/ranging/aidl/vts/Android.bp
+++ b/bluetooth/ranging/aidl/vts/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_bluetooth",
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
@@ -16,8 +17,7 @@
         "libutils",
     ],
     static_libs: [
-        "android.hardware.bluetooth.ranging-V1-ndk",
-        "libbluetooth-types",
+        "android.hardware.bluetooth.ranging-V2-ndk",
     ],
     test_config: "VtsHalBluetoothRangingTargetTest.xml",
     test_suites: [
diff --git a/bluetooth/ranging/aidl/vts/VtsHalBluetoothRangingTargetTest.cpp b/bluetooth/ranging/aidl/vts/VtsHalBluetoothRangingTargetTest.cpp
index 702df95..4510f24 100644
--- a/bluetooth/ranging/aidl/vts/VtsHalBluetoothRangingTargetTest.cpp
+++ b/bluetooth/ranging/aidl/vts/VtsHalBluetoothRangingTargetTest.cpp
@@ -30,12 +30,15 @@
 using aidl::android::hardware::bluetooth::ranging::
     BnBluetoothChannelSoundingSessionCallback;
 using aidl::android::hardware::bluetooth::ranging::ChannelSoudingRawData;
+using aidl::android::hardware::bluetooth::ranging::ChannelSoundingProcedureData;
+using aidl::android::hardware::bluetooth::ranging::Config;
 using aidl::android::hardware::bluetooth::ranging::CsSecurityLevel;
 using aidl::android::hardware::bluetooth::ranging::IBluetoothChannelSounding;
 using aidl::android::hardware::bluetooth::ranging::
     IBluetoothChannelSoundingSession;
 using aidl::android::hardware::bluetooth::ranging::
     IBluetoothChannelSoundingSessionCallback;
+using aidl::android::hardware::bluetooth::ranging::ProcedureEnableConfig;
 using aidl::android::hardware::bluetooth::ranging::RangingResult;
 using aidl::android::hardware::bluetooth::ranging::Reason;
 using aidl::android::hardware::bluetooth::ranging::ResultType;
@@ -43,6 +46,12 @@
 using aidl::android::hardware::bluetooth::ranging::VendorSpecificData;
 using ndk::ScopedAStatus;
 
+enum class RangingHalVersion : uint8_t {
+  V_UNAVAILABLE = 0,
+  V_1,
+  V_2,
+};
+
 class BluetoothChannelSoundingSessionCallback
     : public BnBluetoothChannelSoundingSessionCallback {
  public:
@@ -80,6 +89,8 @@
     ALOGI("SetUp Ranging Test");
     bluetooth_channel_sounding_ = IBluetoothChannelSounding::fromBinder(
         ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    hal_version_ = GetRangingHalVersion();
+    ASSERT_GT(hal_version_, RangingHalVersion::V_UNAVAILABLE);
     ASSERT_NE(bluetooth_channel_sounding_, nullptr);
   }
 
@@ -95,6 +106,8 @@
   ScopedAStatus getSupportedSessionTypes(
       std::optional<std::vector<SessionType>>* _aidl_return);
   ScopedAStatus getMaxSupportedCsSecurityLevel(CsSecurityLevel* _aidl_return);
+  ScopedAStatus getSupportedCsSecurityLevels(
+      std::vector<CsSecurityLevel>* _aidl_return);
   ScopedAStatus openSession(
       const BluetoothChannelSoundingParameters& in_params,
       const std::shared_ptr<IBluetoothChannelSoundingSessionCallback>&
@@ -111,6 +124,30 @@
     return status;
   }
 
+  RangingHalVersion GetRangingHalVersion() {
+    int32_t aidl_version = 0;
+    if (bluetooth_channel_sounding_ == nullptr) {
+      return RangingHalVersion::V_UNAVAILABLE;
+    }
+    auto aidl_ret_val =
+        bluetooth_channel_sounding_->getInterfaceVersion(&aidl_version);
+    if (!aidl_ret_val.isOk()) {
+      return RangingHalVersion::V_UNAVAILABLE;
+    }
+    switch (aidl_version) {
+      case 1:
+        return RangingHalVersion::V_1;
+      case 2:
+        return RangingHalVersion::V_2;
+      default:
+        return RangingHalVersion::V_UNAVAILABLE;
+    }
+    return RangingHalVersion::V_UNAVAILABLE;
+  }
+
+ public:
+  RangingHalVersion hal_version_ = RangingHalVersion::V_UNAVAILABLE;
+
  private:
   std::shared_ptr<IBluetoothChannelSounding> bluetooth_channel_sounding_;
 };
@@ -130,6 +167,13 @@
   return bluetooth_channel_sounding_->getMaxSupportedCsSecurityLevel(
       _aidl_return);
 }
+
+ScopedAStatus BluetoothRangingTest::getSupportedCsSecurityLevels(
+    std::vector<CsSecurityLevel>* _aidl_return) {
+  return bluetooth_channel_sounding_->getSupportedCsSecurityLevels(
+      _aidl_return);
+}
+
 ScopedAStatus BluetoothRangingTest::openSession(
     const BluetoothChannelSoundingParameters& in_params,
     const std::shared_ptr<IBluetoothChannelSoundingSessionCallback>&
@@ -155,11 +199,25 @@
 }
 
 TEST_P(BluetoothRangingTest, GetMaxSupportedCsSecurityLevel) {
+  if (hal_version_ > RangingHalVersion::V_1) {
+    GTEST_SKIP();
+  }
   CsSecurityLevel security_level;
   ScopedAStatus status = getMaxSupportedCsSecurityLevel(&security_level);
   ASSERT_TRUE(status.isOk());
 }
 
+TEST_P(BluetoothRangingTest, GetSupportedCsSecurityLevels) {
+  if (hal_version_ < RangingHalVersion::V_2) {
+    GTEST_SKIP();
+  }
+  std::vector<CsSecurityLevel> supported_security_levels;
+  ScopedAStatus status =
+      getSupportedCsSecurityLevels(&supported_security_levels);
+  ASSERT_GT(static_cast<uint8_t>(supported_security_levels.size()), 0);
+  ASSERT_TRUE(status.isOk());
+}
+
 TEST_P(BluetoothRangingTest, OpenSession) {
   BluetoothChannelSoundingParameters params;
   std::shared_ptr<BluetoothChannelSoundingSessionCallback> callback = nullptr;
@@ -205,6 +263,9 @@
 }
 
 TEST_P(BluetoothRangingTest, WriteRawData) {
+  if (hal_version_ > RangingHalVersion::V_1) {
+    GTEST_SKIP();
+  }
   std::shared_ptr<IBluetoothChannelSoundingSession> session;
   auto status = initBluetoothChannelSoundingSession(&session);
   ASSERT_TRUE(status.isOk());
@@ -215,6 +276,62 @@
   }
 }
 
+TEST_P(BluetoothRangingTest, WriteProcedureData) {
+  if (hal_version_ < RangingHalVersion::V_2) {
+    GTEST_SKIP();
+  }
+  std::shared_ptr<IBluetoothChannelSoundingSession> session;
+  auto status = initBluetoothChannelSoundingSession(&session);
+  ASSERT_TRUE(status.isOk());
+  if (session != nullptr) {
+    ChannelSoundingProcedureData procedure_data;
+    status = session->writeProcedureData(procedure_data);
+    ASSERT_TRUE(status.isOk());
+  }
+}
+
+TEST_P(BluetoothRangingTest, UpdateChannelSoundingConfig) {
+  if (hal_version_ < RangingHalVersion::V_2) {
+    GTEST_SKIP();
+  }
+  std::shared_ptr<IBluetoothChannelSoundingSession> session;
+  auto status = initBluetoothChannelSoundingSession(&session);
+  ASSERT_TRUE(status.isOk());
+  if (session != nullptr) {
+    Config config;
+    status = session->updateChannelSoundingConfig(config);
+    ASSERT_TRUE(status.isOk());
+  }
+}
+
+TEST_P(BluetoothRangingTest, UpdateProcedureEnableConfig) {
+  if (hal_version_ < RangingHalVersion::V_2) {
+    GTEST_SKIP();
+  }
+  std::shared_ptr<IBluetoothChannelSoundingSession> session;
+  auto status = initBluetoothChannelSoundingSession(&session);
+  ASSERT_TRUE(status.isOk());
+  if (session != nullptr) {
+    ProcedureEnableConfig procedure_enable_config;
+    status = session->updateProcedureEnableConfig(procedure_enable_config);
+    ASSERT_TRUE(status.isOk());
+  }
+}
+
+TEST_P(BluetoothRangingTest, UpdateBleConnInterval) {
+  if (hal_version_ < RangingHalVersion::V_2) {
+    GTEST_SKIP();
+  }
+  std::shared_ptr<IBluetoothChannelSoundingSession> session;
+  auto status = initBluetoothChannelSoundingSession(&session);
+  ASSERT_TRUE(status.isOk());
+  if (session != nullptr) {
+    int ble_conn_interval = 10;
+    status = session->updateBleConnInterval(ble_conn_interval);
+    ASSERT_TRUE(status.isOk());
+  }
+}
+
 TEST_P(BluetoothRangingTest, CloseSession) {
   std::shared_ptr<IBluetoothChannelSoundingSession> session;
   auto status = initBluetoothChannelSoundingSession(&session);
diff --git a/bluetooth/socket/OWNERS b/bluetooth/socket/OWNERS
new file mode 100644
index 0000000..e7a60e6
--- /dev/null
+++ b/bluetooth/socket/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 27441
+
+include platform/packages/modules/Bluetooth:/OWNERS
+
+jaydenk@google.com
diff --git a/bluetooth/socket/aidl/Android.bp b/bluetooth/socket/aidl/Android.bp
new file mode 100644
index 0000000..7c03677
--- /dev/null
+++ b/bluetooth/socket/aidl/Android.bp
@@ -0,0 +1,46 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.bluetooth.socket",
+    vendor_available: true,
+    host_supported: true,
+    srcs: ["android/hardware/bluetooth/socket/*.aidl"],
+    imports: [
+        "android.hardware.contexthub-V4",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            enabled: false,
+        },
+        ndk: {
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.bt",
+            ],
+            min_sdk_version: "33",
+        },
+    },
+    frozen: false,
+}
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/ChannelInfo.aidl
similarity index 87%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/ChannelInfo.aidl
index ea3a173..b9b9593 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/ChannelInfo.aidl
@@ -31,9 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.socket;
+@VintfStability
+union ChannelInfo {
+  android.hardware.bluetooth.socket.LeCocChannelInfo leCocChannelInfo;
+  android.hardware.bluetooth.socket.RfcommChannelInfo rfcommChannelInfo;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/IBluetoothSocket.aidl
similarity index 81%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
copy to bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/IBluetoothSocket.aidl
index 5c26cc2..a961692 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/IBluetoothSocket.aidl
@@ -31,7 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-interface IHwCryptoOperations {
-  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+package android.hardware.bluetooth.socket;
+@VintfStability
+interface IBluetoothSocket {
+  void registerCallback(in android.hardware.bluetooth.socket.IBluetoothSocketCallback callback);
+  android.hardware.bluetooth.socket.SocketCapabilities getSocketCapabilities();
+  void opened(in android.hardware.bluetooth.socket.SocketContext context);
+  void closed(long socketId);
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/IBluetoothSocketCallback.aidl
similarity index 86%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/IBluetoothSocketCallback.aidl
index ea3a173..35bfb5b 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/IBluetoothSocketCallback.aidl
@@ -31,9 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.socket;
+@VintfStability
+interface IBluetoothSocketCallback {
+  void openedComplete(long socketId, in android.hardware.bluetooth.socket.Status status, in String reason);
+  void close(long socketId, in String reason);
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/LeCocCapabilities.aidl
similarity index 91%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/LeCocCapabilities.aidl
index ca8b3eb..447daa9 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/LeCocCapabilities.aidl
@@ -31,8 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.bluetooth.socket;
+@VintfStability
+parcelable LeCocCapabilities {
+  int numberOfSupportedSockets;
+  int mtu;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/LeCocChannelInfo.aidl
similarity index 86%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/LeCocChannelInfo.aidl
index ea3a173..4d6fcb7 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/LeCocChannelInfo.aidl
@@ -31,9 +31,16 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.socket;
+@VintfStability
+parcelable LeCocChannelInfo {
+  int localCid;
+  int remoteCid;
+  int psm;
+  int localMtu;
+  int remoteMtu;
+  int localMps;
+  int remoteMps;
+  int initialRxCredits;
+  int initialTxCredits;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/RfcommCapabilities.aidl
similarity index 91%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/RfcommCapabilities.aidl
index ca8b3eb..06a75b4 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/RfcommCapabilities.aidl
@@ -31,8 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.bluetooth.socket;
+@VintfStability
+parcelable RfcommCapabilities {
+  int numberOfSupportedSockets;
+  int maxFrameSize;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/RfcommChannelInfo.aidl
similarity index 86%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/RfcommChannelInfo.aidl
index ea3a173..3f9a140 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/RfcommChannelInfo.aidl
@@ -31,9 +31,16 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.socket;
+@VintfStability
+parcelable RfcommChannelInfo {
+  int localCid;
+  int remoteCid;
+  int localMtu;
+  int remoteMtu;
+  int initialRxCredits;
+  int initialTxCredits;
+  int dlci;
+  int maxFrameSize;
+  boolean muxInitiator;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/SocketCapabilities.aidl
similarity index 86%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/SocketCapabilities.aidl
index ea3a173..400f20c 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/SocketCapabilities.aidl
@@ -31,9 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.socket;
+@VintfStability
+parcelable SocketCapabilities {
+  android.hardware.bluetooth.socket.LeCocCapabilities leCocCapabilities;
+  android.hardware.bluetooth.socket.RfcommCapabilities rfcommCapabilities;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/SocketContext.aidl
similarity index 86%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/SocketContext.aidl
index ea3a173..6844d31 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/SocketContext.aidl
@@ -31,9 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.bluetooth.socket;
+@VintfStability
+parcelable SocketContext {
+  long socketId;
+  String name;
+  int aclConnectionHandle;
+  android.hardware.bluetooth.socket.ChannelInfo channelInfo;
+  android.hardware.contexthub.EndpointId endpointId;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/Status.aidl
similarity index 92%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/Status.aidl
index ca8b3eb..63f57a9 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/bluetooth/socket/aidl/aidl_api/android.hardware.bluetooth.socket/current/android/hardware/bluetooth/socket/Status.aidl
@@ -31,8 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.bluetooth.socket;
+@Backing(type="int") @VintfStability
+enum Status {
+  SUCCESS,
+  FAILURE,
 }
diff --git a/bluetooth/socket/aidl/android/hardware/bluetooth/socket/ChannelInfo.aidl b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/ChannelInfo.aidl
new file mode 100644
index 0000000..afae1c0
--- /dev/null
+++ b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/ChannelInfo.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.socket;
+
+import android.hardware.bluetooth.socket.LeCocChannelInfo;
+import android.hardware.bluetooth.socket.RfcommChannelInfo;
+
+/**
+ * Used to specify the channel information of different protocol.
+ */
+@VintfStability
+union ChannelInfo {
+    /**
+     * LE L2CAP COC channel information.
+     */
+    LeCocChannelInfo leCocChannelInfo;
+
+    /**
+     * RFCOMM channel information.
+     */
+    RfcommChannelInfo rfcommChannelInfo;
+}
diff --git a/bluetooth/socket/aidl/android/hardware/bluetooth/socket/IBluetoothSocket.aidl b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/IBluetoothSocket.aidl
new file mode 100644
index 0000000..5853c10
--- /dev/null
+++ b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/IBluetoothSocket.aidl
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.socket;
+
+import android.hardware.bluetooth.socket.IBluetoothSocketCallback;
+import android.hardware.bluetooth.socket.SocketCapabilities;
+import android.hardware.bluetooth.socket.SocketContext;
+
+/**
+ * The interface for host stack to register callback, get capabilities, and open/close socket.
+ */
+@VintfStability
+interface IBluetoothSocket {
+    /**
+     * API to register a callback for HAL implementation to send asynchronous events.
+     *
+     * @param callback An instance of the |IBluetoothSocketCallback| AIDL interface object
+     */
+    void registerCallback(in IBluetoothSocketCallback callback);
+
+    /**
+     * API to get supported offload socket capabilities.
+     *
+     * @return a socket capabilities
+     */
+    SocketCapabilities getSocketCapabilities();
+
+    /**
+     * API to notify the offload stack that the socket is opened.
+     *
+     * The HAL implementation must use IBluetoothSocketCallback.openedComplete() to indicate the
+     * result of this operation
+     *
+     * @param context Socket context including socket id, channel, hub, and endpoint info
+     */
+    void opened(in SocketContext context);
+
+    /**
+     * API to notify the offload stack that the socket is closed.
+     *
+     * When host app requests to close a socket or the HAL calls IBluetoothSocketCallback.close(),
+     * the host stack closes the socket and sends the notification.
+     *
+     * @param socketId Identifier assigned to the socket by the host stack
+     */
+    void closed(long socketId);
+}
diff --git a/bluetooth/socket/aidl/android/hardware/bluetooth/socket/IBluetoothSocketCallback.aidl b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/IBluetoothSocketCallback.aidl
new file mode 100644
index 0000000..7cd635d
--- /dev/null
+++ b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/IBluetoothSocketCallback.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.socket;
+
+import android.hardware.bluetooth.socket.Status;
+
+/**
+ * The interface from the Bluetooth offload socket to the host stack.
+ */
+@VintfStability
+interface IBluetoothSocketCallback {
+    /**
+     * Invoked when IBluetoothSocket.opened() has been completed.
+     *
+     * @param socketId Identifier assigned to the socket by the host stack
+     * @param status Status indicating success or failure
+     * @param reason Reason string of the operation failure for debugging purposes
+     */
+    void openedComplete(long socketId, in Status status, in String reason);
+
+    /**
+     * Invoked when offload app or stack requests host stack to close the socket.
+     *
+     * @param socketId Identifier assigned to the socket by the host stack
+     * @param reason Reason string for closing the socket for debugging purposes
+     */
+    void close(long socketId, in String reason);
+}
diff --git a/bluetooth/socket/aidl/android/hardware/bluetooth/socket/LeCocCapabilities.aidl b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/LeCocCapabilities.aidl
new file mode 100644
index 0000000..003da11
--- /dev/null
+++ b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/LeCocCapabilities.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.socket;
+
+/**
+ * Capabilities for LE L2CAP COC that the offload stack supports.
+ */
+@VintfStability
+parcelable LeCocCapabilities {
+    /**
+     * Maximum number of LE COC sockets supported. If not supported, the value must be zero.
+     */
+    int numberOfSupportedSockets;
+
+    /**
+     * Local Maximum Transmission Unit size in octets. The MTU size must be in range 23 to 65535.
+     *
+     * The actual value of the local MTU shared in the connection configuration is set in
+     * LeCocChannelInfo.localMtu in the IBluetoothSocket.opened() context parameter.
+     */
+    int mtu;
+
+    /**
+     * The value used by the Host stack for the local Maximum Packet Size shall be the value
+     * LE_ACL_Data_Packet_Length returned by the controller in response to the command HCI LE Read
+     * Buffer Size. Then, the MPS size must be in range 1 to 255. We do not make the MPS
+     * configurable in HAL because using the maximum value does not require a large amount of
+     * memory.
+     */
+}
diff --git a/bluetooth/socket/aidl/android/hardware/bluetooth/socket/LeCocChannelInfo.aidl b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/LeCocChannelInfo.aidl
new file mode 100644
index 0000000..af1bd71
--- /dev/null
+++ b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/LeCocChannelInfo.aidl
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.socket;
+
+/**
+ * LE L2CAP COC channel information
+ */
+@VintfStability
+parcelable LeCocChannelInfo {
+    /**
+     * L2cap local channel ID.
+     */
+    int localCid;
+
+    /**
+     * L2cap remote channel ID.
+     */
+    int remoteCid;
+
+    /**
+     * PSM for L2CAP LE CoC.
+     */
+    int psm;
+
+    /**
+     * Local Maximum Transmission Unit for LE COC specifying the maximum SDU size in bytes that the
+     * local L2CAP layer can receive.
+     */
+    int localMtu;
+
+    /**
+     * Remote Maximum Transmission Unit for LE COC specifying the maximum SDU size in bytes that the
+     * remote L2CAP layer can receive.
+     */
+    int remoteMtu;
+
+    /**
+     * Local Maximum PDU payload Size in bytes that the local L2CAP layer can receive.
+     */
+    int localMps;
+
+    /**
+     * Remote Maximum PDU payload Size in bytes that the remote L2CAP layer can receive.
+     */
+    int remoteMps;
+
+    /**
+     * Protocol initial credits at Rx path.
+     *
+     * The host stack will always set the initial credits to 0 when configuring the L2CAP COC
+     * channel, and this value will always be zero. It means offload stack should send initial
+     * credits to peer device through L2CAP signaling command L2CAP_FLOW_CONTROL_CREDIT_IND when
+     * IBluetoothSocket.opened() is successful.
+     */
+    int initialRxCredits;
+
+    /**
+     * Protocol initial credits at Tx path.
+     */
+    int initialTxCredits;
+}
diff --git a/bluetooth/socket/aidl/android/hardware/bluetooth/socket/RfcommCapabilities.aidl b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/RfcommCapabilities.aidl
new file mode 100644
index 0000000..e5cffff
--- /dev/null
+++ b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/RfcommCapabilities.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.socket;
+
+/**
+ * Capabilities for RFCOMM that the offload stack supports.
+ */
+@VintfStability
+parcelable RfcommCapabilities {
+    /**
+     * Maximum number of RFCOMM sockets supported. If not supported, the value must be zero.
+     */
+    int numberOfSupportedSockets;
+
+    /**
+     * Maximum frame size in octets negotiated during DLCI establishment. The frame size must be
+     * in range 23 to 32767.
+     */
+    int maxFrameSize;
+}
diff --git a/bluetooth/socket/aidl/android/hardware/bluetooth/socket/RfcommChannelInfo.aidl b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/RfcommChannelInfo.aidl
new file mode 100644
index 0000000..7c10144
--- /dev/null
+++ b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/RfcommChannelInfo.aidl
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.socket;
+
+/**
+ * RFCOMM channel information
+ */
+@VintfStability
+parcelable RfcommChannelInfo {
+    /**
+     * L2cap local channel ID for RFCOMM.
+     */
+    int localCid;
+
+    /**
+     * L2cap remote channel ID for RFCOMM.
+     */
+    int remoteCid;
+
+    /**
+     * Local Maximum Transmission Unit Size in bytes that the local L2CAP layer can receive.
+     */
+    int localMtu;
+
+    /**
+     * Remote Maximum Transmission Unit Size in bytes that the remote L2CAP layer can receive.
+     */
+    int remoteMtu;
+
+    /**
+     * Protocol initial credits at Rx path.
+     *
+     * The host stack will always set the initial credits to 0 when configuring the RFCOMM
+     * channel, and this value will always be zero. It means offload stack should send initial
+     * credits to peer device when IBluetoothSocket.opened() is successful.
+     */
+    int initialRxCredits;
+
+    /**
+     * Protocol initial credits at Tx path.
+     */
+    int initialTxCredits;
+
+    /**
+     * Data Link Connection Identifier (DLCI).
+     */
+    int dlci;
+
+    /**
+     * Maximum frame size negotiated during DLCI establishment.
+     */
+    int maxFrameSize;
+
+    /**
+     * Flag of whether the Android stack initiated the RFCOMM multiplexer control channel.
+     *
+     * This flag determines the value of the Command/Response (C/R) bit of RFCOMM frames.
+     */
+    boolean muxInitiator;
+}
diff --git a/bluetooth/socket/aidl/android/hardware/bluetooth/socket/SocketCapabilities.aidl b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/SocketCapabilities.aidl
new file mode 100644
index 0000000..05a59ee
--- /dev/null
+++ b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/SocketCapabilities.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.socket;
+
+import android.hardware.bluetooth.socket.LeCocCapabilities;
+import android.hardware.bluetooth.socket.RfcommCapabilities;
+
+/**
+ * Supported socket protocol capabilities.
+ */
+@VintfStability
+parcelable SocketCapabilities {
+    /**
+     * Supported LE CoC protocol capabilities.
+     */
+    LeCocCapabilities leCocCapabilities;
+
+    /**
+     * Supported RFCOMM protocol capabilities.
+     */
+    RfcommCapabilities rfcommCapabilities;
+}
diff --git a/bluetooth/socket/aidl/android/hardware/bluetooth/socket/SocketContext.aidl b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/SocketContext.aidl
new file mode 100644
index 0000000..1f9be07
--- /dev/null
+++ b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/SocketContext.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.socket;
+
+import android.hardware.bluetooth.socket.ChannelInfo;
+import android.hardware.contexthub.EndpointId;
+
+/**
+ * Socket context.
+ */
+@VintfStability
+parcelable SocketContext {
+    /**
+     * Identifier assigned to the socket by the host stack when the socket is connected to a remote
+     * device. Used to uniquely identify the socket in other callbacks and method invocations. It is
+     * valid only while the socket is connected.
+     */
+    long socketId;
+
+    /**
+     * Descriptive socket name provided by the host app when it creates this socket. This is not
+     * unique across the system, but can help the offload app understand the purpose of the socket
+     * when it receives a socket connection event.
+     */
+    String name;
+
+    /**
+     * ACL connection handle for the socket.
+     */
+    int aclConnectionHandle;
+
+    /**
+     * Channel information of the socket protocol.
+     */
+    ChannelInfo channelInfo;
+
+    /**
+     * Unique identifier for an endpoint at the hardware offload data path.
+     */
+    EndpointId endpointId;
+}
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/Void.aidl b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/Status.aidl
similarity index 82%
copy from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/Void.aidl
copy to bluetooth/socket/aidl/android/hardware/bluetooth/socket/Status.aidl
index f9f608d..d881b09 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/Void.aidl
+++ b/bluetooth/socket/aidl/android/hardware/bluetooth/socket/Status.aidl
@@ -13,6 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.hardware.security.see.hwcrypto.types;
 
-parcelable Void {}
+package android.hardware.bluetooth.socket;
+
+@VintfStability
+@Backing(type="int")
+enum Status {
+    SUCCESS,
+    FAILURE,
+}
diff --git a/bluetooth/socket/aidl/default/Android.bp b/bluetooth/socket/aidl/default/Android.bp
new file mode 100644
index 0000000..a730057
--- /dev/null
+++ b/bluetooth/socket/aidl/default/Android.bp
@@ -0,0 +1,48 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_binary {
+    name: "android.hardware.bluetooth.socket-service.default",
+    relative_install_path: "hw",
+    init_rc: ["bluetooth-socket-service-default.rc"],
+    vintf_fragments: [":manifest_android.hardware.bluetooth.socket-service.default.xml"],
+    vendor: true,
+    srcs: [
+        "BluetoothSocket.cpp",
+        "service.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.bluetooth.socket-V1-ndk",
+        "libbase",
+        "libbinder_ndk",
+        "libhidlbase",
+        "libutils",
+        "liblog",
+    ],
+}
+
+cc_fuzz {
+    name: "android.hardware.bluetooth.socket-service_fuzzer",
+    team: "trendy_team_bluetooth",
+    defaults: ["service_fuzzer_defaults"],
+    srcs: [
+        "fuzzer.cpp",
+        "BluetoothSocket.cpp",
+    ],
+    static_libs: [
+        "android.hardware.bluetooth.socket-V1-ndk",
+        "android.hardware.contexthub-V4-ndk",
+        "liblog",
+    ],
+    fuzz_config: {
+        cc: [
+            "jaydenk@google.com",
+        ],
+    },
+}
+
+filegroup {
+    name: "manifest_android.hardware.bluetooth.socket-service.default.xml",
+    srcs: ["bluetooth-socket-service-default.xml"],
+}
diff --git a/bluetooth/socket/aidl/default/BluetoothSocket.cpp b/bluetooth/socket/aidl/default/BluetoothSocket.cpp
new file mode 100644
index 0000000..5993393
--- /dev/null
+++ b/bluetooth/socket/aidl/default/BluetoothSocket.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 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 "BluetoothSocket.h"
+
+using aidl::android::hardware::bluetooth::socket::Status;
+
+namespace aidl::android::hardware::bluetooth::socket::impl {
+
+BluetoothSocket::BluetoothSocket() {}
+BluetoothSocket::~BluetoothSocket() {}
+
+::ndk::ScopedAStatus BluetoothSocket::registerCallback(
+    const std::shared_ptr<
+        ::aidl::android::hardware::bluetooth::socket::IBluetoothSocketCallback>&
+        in_callback) {
+  if (in_callback == nullptr) {
+    return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
+  }
+  callback_ = in_callback;
+  return ::ndk::ScopedAStatus::ok();
+}
+::ndk::ScopedAStatus BluetoothSocket::getSocketCapabilities(
+    ::aidl::android::hardware::bluetooth::socket::SocketCapabilities*
+        _aidl_return) {
+  _aidl_return->leCocCapabilities.numberOfSupportedSockets = 0;
+  _aidl_return->leCocCapabilities.mtu = 0;
+  _aidl_return->rfcommCapabilities.numberOfSupportedSockets = 0;
+  _aidl_return->rfcommCapabilities.maxFrameSize = 0;
+  return ::ndk::ScopedAStatus::ok();
+}
+::ndk::ScopedAStatus BluetoothSocket::opened(
+    const ::aidl::android::hardware::bluetooth::socket::SocketContext&
+    /* in_context */) {
+  return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+::ndk::ScopedAStatus BluetoothSocket::closed(int64_t /*in_socketId*/) {
+  return ::ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::bluetooth::socket::impl
diff --git a/bluetooth/socket/aidl/default/BluetoothSocket.h b/bluetooth/socket/aidl/default/BluetoothSocket.h
new file mode 100644
index 0000000..9bb41ec
--- /dev/null
+++ b/bluetooth/socket/aidl/default/BluetoothSocket.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 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 <aidl/android/hardware/bluetooth/socket/BnBluetoothSocket.h>
+
+namespace aidl::android::hardware::bluetooth::socket::impl {
+
+class BluetoothSocket : public BnBluetoothSocket {
+ public:
+  BluetoothSocket();
+  ~BluetoothSocket();
+
+  ::ndk::ScopedAStatus registerCallback(
+      const std::shared_ptr<::aidl::android::hardware::bluetooth::socket::
+                                IBluetoothSocketCallback>& in_callback)
+      override;
+  ::ndk::ScopedAStatus getSocketCapabilities(
+      ::aidl::android::hardware::bluetooth::socket::SocketCapabilities*
+          _aidl_return) override;
+  ::ndk::ScopedAStatus opened(
+      const ::aidl::android::hardware::bluetooth::socket::SocketContext&
+          in_context) override;
+  ::ndk::ScopedAStatus closed(int64_t in_socketId) override;
+
+ private:
+  std::shared_ptr<IBluetoothSocketCallback> callback_;
+};
+
+}  // namespace aidl::android::hardware::bluetooth::socket::impl
diff --git a/bluetooth/socket/aidl/default/bluetooth-socket-service-default.rc b/bluetooth/socket/aidl/default/bluetooth-socket-service-default.rc
new file mode 100644
index 0000000..f1eb7f7
--- /dev/null
+++ b/bluetooth/socket/aidl/default/bluetooth-socket-service-default.rc
@@ -0,0 +1,4 @@
+service vendor.bluetooth.socket-default /vendor/bin/hw/android.hardware.bluetooth.socket-service.default
+    class hal
+    user nobody
+    group nobody
diff --git a/bluetooth/socket/aidl/default/bluetooth-socket-service-default.xml b/bluetooth/socket/aidl/default/bluetooth-socket-service-default.xml
new file mode 100644
index 0000000..b97074d
--- /dev/null
+++ b/bluetooth/socket/aidl/default/bluetooth-socket-service-default.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.bluetooth.socket</name>
+        <version>1</version>
+        <fqname>IBluetoothSocket/default</fqname>
+    </hal>
+</manifest>
diff --git a/bluetooth/socket/aidl/default/fuzzer.cpp b/bluetooth/socket/aidl/default/fuzzer.cpp
new file mode 100644
index 0000000..062db0f
--- /dev/null
+++ b/bluetooth/socket/aidl/default/fuzzer.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 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 <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "BluetoothSocket.h"
+
+using ::aidl::android::hardware::bluetooth::socket::impl::BluetoothSocket;
+using ::android::fuzzService;
+using ::ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  auto bluetoothSocketAidl = SharedRefBase::make<BluetoothSocket>();
+
+  fuzzService(bluetoothSocketAidl->asBinder().get(),
+              FuzzedDataProvider(data, size));
+
+  return 0;
+}
diff --git a/bluetooth/socket/aidl/default/service.cpp b/bluetooth/socket/aidl/default/service.cpp
new file mode 100644
index 0000000..bd15084
--- /dev/null
+++ b/bluetooth/socket/aidl/default/service.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "aidl.android.hardware.bluetooth.socket.service.default"
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <utils/Log.h>
+
+#include "BluetoothSocket.h"
+
+using ::aidl::android::hardware::bluetooth::socket::impl::BluetoothSocket;
+
+int main(int /* argc */, char** /* argv */) {
+  ALOGI("Bluetooth Socket HAL registering");
+  if (!ABinderProcess_setThreadPoolMaxThreadCount(0)) {
+    ALOGE("Failed to set thread pool max thread count");
+    return 1;
+  }
+
+  std::shared_ptr<BluetoothSocket> service =
+      ndk::SharedRefBase::make<BluetoothSocket>();
+  std::string instance =
+      std::string() + BluetoothSocket::descriptor + "/default";
+  auto result =
+      AServiceManager_addService(service->asBinder().get(), instance.c_str());
+  if (result == STATUS_OK) {
+    ABinderProcess_joinThreadPool();
+  } else {
+    ALOGE("Could not register as a service!");
+  }
+  return EXIT_FAILURE;
+}
diff --git a/bluetooth/socket/aidl/vts/Android.bp b/bluetooth/socket/aidl/vts/Android.bp
new file mode 100644
index 0000000..c1ba562
--- /dev/null
+++ b/bluetooth/socket/aidl/vts/Android.bp
@@ -0,0 +1,28 @@
+package {
+    default_team: "trendy_team_bluetooth",
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsHalBluetoothSocketTargetTest",
+    defaults: [
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalBluetoothSocketTargetTest.cpp"],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
+    static_libs: [
+        "android.hardware.bluetooth.socket-V1-ndk",
+        "android.hardware.contexthub-V4-ndk",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+    require_root: true,
+}
diff --git a/bluetooth/socket/aidl/vts/VtsHalBluetoothSocketTargetTest.cpp b/bluetooth/socket/aidl/vts/VtsHalBluetoothSocketTargetTest.cpp
new file mode 100644
index 0000000..1069207
--- /dev/null
+++ b/bluetooth/socket/aidl/vts/VtsHalBluetoothSocketTargetTest.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2024 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 <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/bluetooth/socket/BnBluetoothSocketCallback.h>
+#include <aidl/android/hardware/bluetooth/socket/IBluetoothSocket.h>
+#include <aidl/android/hardware/bluetooth/socket/IBluetoothSocketCallback.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+#include <future>
+
+using ::aidl::android::hardware::bluetooth::socket::BnBluetoothSocketCallback;
+using ::aidl::android::hardware::bluetooth::socket::IBluetoothSocket;
+using ::aidl::android::hardware::bluetooth::socket::SocketCapabilities;
+using ::aidl::android::hardware::bluetooth::socket::SocketContext;
+using ::ndk::ScopedAStatus;
+
+namespace {
+constexpr static int kCallbackTimeoutMs = 250;
+constexpr static int kOpenedCallbackTimeoutMs = 5000;
+}  // namespace
+
+class BluetoothSocketCallback : public BnBluetoothSocketCallback {
+ public:
+  BluetoothSocketCallback(
+      const std::function<
+          void(int64_t in_socketId,
+               ::aidl::android::hardware::bluetooth::socket::Status in_status,
+               const std::string& in_reason)>& on_hal_opened_complete_cb)
+      : on_hal_opened_complete_cb_(on_hal_opened_complete_cb) {}
+
+  ScopedAStatus openedComplete(
+      int64_t in_socketId,
+      ::aidl::android::hardware::bluetooth::socket::Status in_status,
+      const std::string& in_reason) override {
+    on_hal_opened_complete_cb_(in_socketId, in_status, in_reason);
+    return ::ndk::ScopedAStatus::ok();
+  }
+
+  ScopedAStatus close(int64_t /* in_socketId */,
+                      const std::string& /* in_reason */) override {
+    return ::ndk::ScopedAStatus::ok();
+  }
+
+ private:
+  std::function<void(
+      int64_t in_socketId,
+      ::aidl::android::hardware::bluetooth::socket::Status in_status,
+      const std::string& in_reason)>
+      on_hal_opened_complete_cb_;
+};
+
+class BluetoothSocketTest : public ::testing::TestWithParam<std::string> {
+ public:
+  virtual void SetUp() override {
+    ALOGI("SetUp Socket Test");
+    bluetooth_socket_ = IBluetoothSocket::fromBinder(
+        ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(bluetooth_socket_, nullptr);
+  }
+
+  virtual void TearDown() override {
+    ALOGI("TearDown Socket Test");
+    bluetooth_socket_ = nullptr;
+    ASSERT_EQ(bluetooth_socket_, nullptr);
+  }
+
+  std::shared_ptr<IBluetoothSocket> bluetooth_socket_;
+};
+
+TEST_P(BluetoothSocketTest, registerCallback) {
+  std::promise<void> open_cb_promise;
+  std::future<void> open_cb_future{open_cb_promise.get_future()};
+  std::shared_ptr<BluetoothSocketCallback> callback =
+      ndk::SharedRefBase::make<BluetoothSocketCallback>(
+          [&open_cb_promise](auto /* socket_id */, auto /* status */,
+                             auto /* reason */) {
+            open_cb_promise.set_value();
+          });
+  ScopedAStatus status = bluetooth_socket_->registerCallback(callback);
+  ASSERT_TRUE(status.isOk());
+}
+
+TEST_P(BluetoothSocketTest, GetSocketCapabilities) {
+  SocketCapabilities socket_capabilities;
+  ScopedAStatus status =
+      bluetooth_socket_->getSocketCapabilities(&socket_capabilities);
+  ASSERT_TRUE(status.isOk());
+  ASSERT_TRUE(socket_capabilities.leCocCapabilities.numberOfSupportedSockets >=
+              0);
+  if (socket_capabilities.leCocCapabilities.numberOfSupportedSockets) {
+    // When LE COC is supported, the local MTU must be configured within the
+    // valid range defined in the L2CAP specification.
+    ASSERT_TRUE(socket_capabilities.leCocCapabilities.mtu >= 23 &&
+                socket_capabilities.leCocCapabilities.mtu <= 65535);
+  }
+  ASSERT_TRUE(socket_capabilities.rfcommCapabilities.numberOfSupportedSockets >=
+              0);
+  if (socket_capabilities.rfcommCapabilities.numberOfSupportedSockets) {
+    // When RFCOMM is supported, the maximum frame size must be configured
+    // within the valid range defined in the RFCOMM specification.
+    ASSERT_TRUE(socket_capabilities.rfcommCapabilities.maxFrameSize >= 23 &&
+                socket_capabilities.rfcommCapabilities.maxFrameSize <= 32767);
+  }
+}
+
+TEST_P(BluetoothSocketTest, Opened) {
+  std::promise<void> open_cb_promise;
+  std::future<void> open_cb_future{open_cb_promise.get_future()};
+  std::shared_ptr<BluetoothSocketCallback> callback =
+      ndk::SharedRefBase::make<BluetoothSocketCallback>(
+          [&open_cb_promise](auto /* socket_id */, auto /* status */,
+                             auto /* reason */) {
+            open_cb_promise.set_value();
+          });
+  bluetooth_socket_->registerCallback(callback);
+  SocketCapabilities socket_capabilities;
+  bluetooth_socket_->getSocketCapabilities(&socket_capabilities);
+
+  SocketContext socket_context;
+  ScopedAStatus status = bluetooth_socket_->opened(socket_context);
+  std::chrono::milliseconds timeout{kOpenedCallbackTimeoutMs};
+  if (status.isOk()) {
+    // If IBluetoothSocket.opened() returns success, the callback
+    // BluetoothSocketCallback.openedComplete() must be called within the
+    // timeout.
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+  } else {
+    // If IBluetoothSocket.opened() returns failure, the callback
+    // BluetoothSocketCallback.openedComplete() must not be called.
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::timeout);
+  }
+}
+
+TEST_P(BluetoothSocketTest, Closed) {
+  std::promise<void> open_cb_promise;
+  std::future<void> open_cb_future{open_cb_promise.get_future()};
+  std::shared_ptr<BluetoothSocketCallback> callback =
+      ndk::SharedRefBase::make<BluetoothSocketCallback>(
+          [&open_cb_promise](auto /* socket_id */, auto /* status */,
+                             auto /* reason */) {
+            open_cb_promise.set_value();
+          });
+  bluetooth_socket_->registerCallback(callback);
+  SocketCapabilities socket_capabilities;
+  bluetooth_socket_->getSocketCapabilities(&socket_capabilities);
+
+  long socket_id = 1;
+  bluetooth_socket_->closed(socket_id);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothSocketTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothSocketTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothSocket::descriptor)),
+                         android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  ABinderProcess_startThreadPool();
+  int status = RUN_ALL_TESTS();
+  ALOGI("Test result = %d", status);
+  return status;
+}
diff --git a/boot/1.0/vts/functional/Android.bp b/boot/1.0/vts/functional/Android.bp
index 90ee9cb..b49772c 100644
--- a/boot/1.0/vts/functional/Android.bp
+++ b/boot/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/boot/1.1/vts/functional/Android.bp b/boot/1.1/vts/functional/Android.bp
index 3a36046..6e44996 100644
--- a/boot/1.1/vts/functional/Android.bp
+++ b/boot/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/boot/1.2/vts/functional/Android.bp b/boot/1.2/vts/functional/Android.bp
index 7d546ed..ba186bf 100644
--- a/boot/1.2/vts/functional/Android.bp
+++ b/boot/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/boot/aidl/client/BootControlClient.cpp b/boot/aidl/client/BootControlClient.cpp
index 89258d2..7aab5b4 100644
--- a/boot/aidl/client/BootControlClient.cpp
+++ b/boot/aidl/client/BootControlClient.cpp
@@ -18,6 +18,7 @@
 
 #include <aidl/android/hardware/boot/IBootControl.h>
 #include <android-base/logging.h>
+#include <android/binder_ibinder.h>
 #include <android/binder_manager.h>
 #include <android/hardware/boot/1.0/IBootControl.h>
 #include <android/hardware/boot/1.1/IBootControl.h>
@@ -36,6 +37,17 @@
 
 using aidl::android::hardware::boot::MergeStatus;
 
+#define TEST_OP(_x, _y, op)                                                            \
+    do {                                                                               \
+        const auto& x = _x;                                                            \
+        const auto& y = _y;                                                            \
+        if (!(x op y)) {                                                               \
+            LOG(ERROR) << #_x " " #op " " #_y << " failed: " << x << " " #op " " << y; \
+            return {};                                                                 \
+        }                                                                              \
+    } while (0)
+#define TEST_NE(_x, _y) TEST_OP(_x, _y, !=)
+
 std::ostream& operator<<(std::ostream& os, MergeStatus status) {
     switch (status) {
         case MergeStatus::NONE:
@@ -65,85 +77,145 @@
     using IBootControl = ::aidl::android::hardware::boot::IBootControl;
 
   public:
-    BootControlClientAidl(std::shared_ptr<IBootControl> module) : module_(module) {}
+    explicit BootControlClientAidl(std::shared_ptr<IBootControl> module)
+        : module_(module),
+          boot_control_death_recipient(AIBinder_DeathRecipient_new(onBootControlServiceDied)) {
+        AIBinder_DeathRecipient_setOnUnlinked(boot_control_death_recipient, onCallbackUnlinked);
+        binder_status_t status =
+                AIBinder_linkToDeath(module->asBinder().get(), boot_control_death_recipient, this);
+        if (status != STATUS_OK) {
+            LOG(ERROR) << "Could not link to binder death";
+            return;
+        }
+    }
 
     BootControlVersion GetVersion() const override { return BootControlVersion::BOOTCTL_AIDL; }
 
-    ~BootControlClientAidl() = default;
-    virtual int32_t GetNumSlots() const {
+    void onBootControlServiceDied() {
+        LOG(ERROR) << "boot control service AIDL died. Attempting to reconnect...";
+        const auto instance_name =
+                std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
+        if (AServiceManager_isDeclared(instance_name.c_str())) {
+            module_ = ::aidl::android::hardware::boot::IBootControl::fromBinder(
+                    ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
+            if (module_ == nullptr) {
+                LOG(ERROR) << "AIDL " << instance_name
+                           << " is declared but waitForService returned nullptr when trying to "
+                              "reconnect boot control service";
+                return;
+            }
+            LOG(INFO) << "Reconnected to AIDL version of IBootControl";
+            binder_status_t status = AIBinder_linkToDeath(module_->asBinder().get(),
+                                                          boot_control_death_recipient, this);
+            if (status != STATUS_OK) {
+                LOG(ERROR) << "Could not link to binder death";
+                return;
+            }
+
+        } else {
+            LOG(ERROR) << "Failed to get service manager for: " << instance_name;
+        }
+    }
+
+    int32_t GetNumSlots() const override {
         int32_t ret = -1;
+        if (!module_) {
+            LOG(ERROR) << "bootctl module not set";
+            return ret;
+        }
         LOG_NDK_STATUS(module_->getNumberSlots(&ret));
         return ret;
     }
 
-    int32_t GetCurrentSlot() const {
+    int32_t GetCurrentSlot() const override {
         int32_t ret = -1;
+        if (!module_) {
+            LOG(ERROR) << "bootctl module not set";
+            return ret;
+        }
         LOG_NDK_STATUS(module_->getCurrentSlot(&ret));
         return ret;
     }
-    MergeStatus getSnapshotMergeStatus() const {
+
+    MergeStatus getSnapshotMergeStatus() const override {
         MergeStatus status = MergeStatus::UNKNOWN;
+        if (!module_) {
+            LOG(ERROR) << "bootctl module not set";
+            return status;
+        }
         LOG_NDK_STATUS(module_->getSnapshotMergeStatus(&status));
         return status;
     }
-    std::string GetSuffix(int32_t slot) const {
+
+    std::string GetSuffix(int32_t slot) const override {
+        TEST_NE(module_, nullptr);
         std::string ret;
         const auto status = module_->getSuffix(slot, &ret);
         if (!status.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << status.getDescription();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
+                       << status.getDescription();
             return {};
         }
         return ret;
     }
 
-    std::optional<bool> IsSlotBootable(int32_t slot) const {
+    std::optional<bool> IsSlotBootable(int32_t slot) const override {
+        TEST_NE(module_, nullptr);
         bool ret = false;
         const auto status = module_->isSlotBootable(slot, &ret);
         if (!status.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << status.getDescription();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
+                       << status.getDescription();
             return {};
         }
         return ret;
     }
 
-    CommandResult MarkSlotUnbootable(int32_t slot) {
+    CommandResult MarkSlotUnbootable(int32_t slot) override {
+        TEST_NE(module_, nullptr);
         const auto status = module_->setSlotAsUnbootable(slot);
         if (!status.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << status.getDescription();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
+                       << status.getDescription();
         }
         return {.success = status.isOk(), .errMsg = status.getDescription()};
     }
 
-    CommandResult SetActiveBootSlot(int slot) {
+    CommandResult SetActiveBootSlot(int slot) override {
+        TEST_NE(module_, nullptr);
         const auto status = module_->setActiveBootSlot(slot);
         if (!status.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << status.getDescription();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
+                       << status.getDescription();
         }
         return {.success = status.isOk(), .errMsg = status.getDescription()};
     }
+
     int GetActiveBootSlot() const {
         int ret = -1;
+        if (!module_) {
+            LOG(ERROR) << "bootctl module not set";
+            return ret;
+        }
         LOG_NDK_STATUS(module_->getActiveBootSlot(&ret));
         return ret;
     }
 
     // Check if |slot| is marked boot successfully.
-    std::optional<bool> IsSlotMarkedSuccessful(int slot) const {
+    std::optional<bool> IsSlotMarkedSuccessful(int slot) const override {
+        TEST_NE(module_, nullptr);
         bool ret = false;
         const auto status = module_->isSlotMarkedSuccessful(slot, &ret);
         if (!status.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << status.getDescription();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
+                       << status.getDescription();
             return {};
         }
         return ret;
     }
 
-    CommandResult MarkBootSuccessful() {
+    CommandResult MarkBootSuccessful() override {
+        TEST_NE(module_, nullptr);
         const auto status = module_->markBootSuccessful();
         if (!status.isOk()) {
             LOG(ERROR) << __FUNCTION__ << " failed " << status.getDescription();
@@ -151,17 +223,29 @@
         return {.success = status.isOk(), .errMsg = status.getDescription()};
     }
 
-    CommandResult SetSnapshotMergeStatus(aidl::android::hardware::boot::MergeStatus merge_status) {
+    CommandResult SetSnapshotMergeStatus(
+            aidl::android::hardware::boot::MergeStatus merge_status) override {
+        TEST_NE(module_, nullptr);
         const auto status = module_->setSnapshotMergeStatus(merge_status);
         if (!status.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")"
-                       << " failed " << status.getDescription();
+            LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
+                       << status.getDescription();
         }
         return {.success = status.isOk(), .errMsg = status.getDescription()};
     }
 
   private:
-    const std::shared_ptr<IBootControl> module_;
+    std::shared_ptr<IBootControl> module_;
+    AIBinder_DeathRecipient* boot_control_death_recipient;
+    static void onCallbackUnlinked(void* /*client*/) {
+        // this is an empty function needed to suppress the "AIBinder_linkToDeath is being called
+        // with a non-null cookie and no onUnlink callback set. This might not be intended.
+        // AIBinder_DeathRecipient_setOnUnlinked should be called first." warning
+    }
+    static void onBootControlServiceDied(void* client) {
+        BootControlClientAidl* self = static_cast<BootControlClientAidl*>(client);
+        self->onBootControlServiceDied();
+    }
 };
 
 using namespace android::hardware::boot;
@@ -183,7 +267,7 @@
             return BootControlVersion::BOOTCTL_V1_0;
         }
     }
-    int32_t GetNumSlots() const {
+    int32_t GetNumSlots() const override {
         const auto ret = module_v1_->getNumberSlots();
         if (!ret.isOk()) {
             LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
@@ -191,7 +275,7 @@
         return ret.withDefault(-1);
     }
 
-    int32_t GetCurrentSlot() const {
+    int32_t GetCurrentSlot() const override {
         const auto ret = module_v1_->getCurrentSlot();
         if (!ret.isOk()) {
             LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
@@ -199,23 +283,21 @@
         return ret.withDefault(-1);
     }
 
-    std::string GetSuffix(int32_t slot) const {
+    std::string GetSuffix(int32_t slot) const override {
         std::string suffix;
         const auto ret = module_v1_->getSuffix(
                 slot,
                 [&](const ::android::hardware::hidl_string& slotSuffix) { suffix = slotSuffix; });
         if (!ret.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << ret.description();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
         }
         return suffix;
     }
 
-    std::optional<bool> IsSlotBootable(int32_t slot) const {
+    std::optional<bool> IsSlotBootable(int32_t slot) const override {
         const auto ret = module_v1_->isSlotBootable(slot);
         if (!ret.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << ret.description();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
             return {};
         }
         const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
@@ -225,7 +307,7 @@
         return bool_result == V1_0::BoolResult::TRUE;
     }
 
-    CommandResult MarkSlotUnbootable(int32_t slot) {
+    CommandResult MarkSlotUnbootable(int32_t slot) override {
         CommandResult result;
         const auto ret =
                 module_v1_->setSlotAsUnbootable(slot, [&](const V1_0::CommandResult& error) {
@@ -233,26 +315,24 @@
                     result.errMsg = error.errMsg;
                 });
         if (!ret.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << ret.description();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
         }
         return result;
     }
 
-    CommandResult SetActiveBootSlot(int32_t slot) {
+    CommandResult SetActiveBootSlot(int32_t slot) override {
         CommandResult result;
         const auto ret = module_v1_->setActiveBootSlot(slot, [&](const V1_0::CommandResult& error) {
             result.success = error.success;
             result.errMsg = error.errMsg;
         });
         if (!ret.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << ret.description();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
         }
         return result;
     }
 
-    CommandResult MarkBootSuccessful() {
+    CommandResult MarkBootSuccessful() override {
         CommandResult result;
         const auto ret = module_v1_->markBootSuccessful([&](const V1_0::CommandResult& error) {
             result.success = error.success;
@@ -264,11 +344,10 @@
         return result;
     }
 
-    std::optional<bool> IsSlotMarkedSuccessful(int32_t slot) const {
+    std::optional<bool> IsSlotMarkedSuccessful(int32_t slot) const override {
         const auto ret = module_v1_->isSlotMarkedSuccessful(slot);
         if (!ret.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << ret.description();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
             return {};
         }
         const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
@@ -278,7 +357,7 @@
         return bool_result == V1_0::BoolResult::TRUE;
     }
 
-    MergeStatus getSnapshotMergeStatus() const {
+    MergeStatus getSnapshotMergeStatus() const override {
         if (module_v1_1_ == nullptr) {
             LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.1";
             return MergeStatus::UNKNOWN;
@@ -291,7 +370,7 @@
                 ret.withDefault(static_cast<V1_1::MergeStatus>(MergeStatus::UNKNOWN)));
     }
 
-    CommandResult SetSnapshotMergeStatus(MergeStatus merge_status) {
+    CommandResult SetSnapshotMergeStatus(MergeStatus merge_status) override {
         if (module_v1_1_ == nullptr) {
             return {.success = false,
                     .errMsg = "setSnapshotMergeStatus is unsupported, requires at least boot v1.1"};
@@ -299,13 +378,13 @@
         const auto ret =
                 module_v1_1_->setSnapshotMergeStatus(static_cast<V1_1::MergeStatus>(merge_status));
         if (!ret.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")"
-                       << " failed " << ret.description();
+            LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
+                       << ret.description();
         }
         return {.success = ret.isOk(), .errMsg = ret.description()};
     }
 
-    int32_t GetActiveBootSlot() const {
+    int32_t GetActiveBootSlot() const override {
         if (module_v1_2_ == nullptr) {
             LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.2";
             return -1;
@@ -326,7 +405,6 @@
 std::unique_ptr<BootControlClient> BootControlClient::WaitForService() {
     const auto instance_name =
             std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
-
     if (AServiceManager_isDeclared(instance_name.c_str())) {
         auto module = ::aidl::android::hardware::boot::IBootControl::fromBinder(
                 ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
diff --git a/boot/aidl/default/Android.bp b/boot/aidl/default/Android.bp
index c1d3c57..2fd2dad 100644
--- a/boot/aidl/default/Android.bp
+++ b/boot/aidl/default/Android.bp
@@ -57,7 +57,7 @@
     name: "android.hardware.boot-service.default_recovery",
     defaults: ["android.hardware.boot-service_common"],
     init_rc: ["android.hardware.boot-service.default_recovery.rc"],
-    vintf_fragments: ["android.hardware.boot-service.default.xml"],
+    vintf_fragment_modules: ["android.hardware.boot-service.default.xml.recovery"],
     recovery: true,
 
     shared_libs: [
@@ -77,11 +77,16 @@
     installable: false,
 }
 
-prebuilt_etc {
+vintf_fragment {
+    name: "android.hardware.boot-service.default.xml.recovery",
+    src: "android.hardware.boot-service.default.xml",
+    recovery: true,
+}
+
+vintf_fragment {
     name: "android.hardware.boot-service.default.xml",
     src: "android.hardware.boot-service.default.xml",
-    sub_dir: "vintf",
-    installable: false,
+    vendor: true,
 }
 
 apex {
@@ -98,6 +103,8 @@
     ],
     prebuilts: [
         "android.hardware.boot-service.default.rc",
+    ],
+    vintf_fragment_modules: [
         "android.hardware.boot-service.default.xml",
     ],
 }
diff --git a/boot/aidl/vts/functional/Android.bp b/boot/aidl/vts/functional/Android.bp
index e46cbef..0310716 100644
--- a/boot/aidl/vts/functional/Android.bp
+++ b/boot/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp b/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp
index 93c8376..228e2af 100644
--- a/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp
+++ b/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp
@@ -84,20 +84,20 @@
 
     for (int s = 0; s < 2; s++) {
         const auto result = boot->setActiveBootSlot(s);
-        ASSERT_TRUE(result.isOk());
+        ASSERT_TRUE(result.isOk()) << result;
     }
     {
         // Restore original flags to avoid problems on reboot
         auto result = boot->setActiveBootSlot(curSlot);
-        ASSERT_TRUE(result.isOk());
+        ASSERT_TRUE(result.isOk()) << result;
 
         if (!otherBootable) {
             const auto result = boot->setSlotAsUnbootable(otherSlot);
-            ASSERT_TRUE(result.isOk());
+            ASSERT_TRUE(result.isOk()) << result;
         }
 
         result = boot->markBootSuccessful();
-        ASSERT_TRUE(result.isOk());
+        ASSERT_TRUE(result.isOk()) << result;
     }
     {
         int slots = 0;
@@ -116,19 +116,19 @@
     boot->isSlotBootable(otherSlot, &otherBootable);
     {
         auto result = boot->setSlotAsUnbootable(otherSlot);
-        ASSERT_TRUE(result.isOk());
+        ASSERT_TRUE(result.isOk()) << result;
         boot->isSlotBootable(otherSlot, &otherBootable);
         ASSERT_FALSE(otherBootable);
 
         // Restore original flags to avoid problems on reboot
         if (otherBootable) {
             result = boot->setActiveBootSlot(otherSlot);
-            ASSERT_TRUE(result.isOk());
+            ASSERT_TRUE(result.isOk()) << result;
         }
         result = boot->setActiveBootSlot(curSlot);
-        ASSERT_TRUE(result.isOk());
+        ASSERT_TRUE(result.isOk()) << result;
         result = boot->markBootSuccessful();
-        ASSERT_TRUE(result.isOk());
+        ASSERT_TRUE(result.isOk()) << result;
     }
     {
         int32_t slots = 0;
@@ -143,7 +143,7 @@
     for (int s = 0; s < 2; s++) {
         bool bootable = false;
         const auto res = boot->isSlotBootable(s, &bootable);
-        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_TRUE(res.isOk()) << res;
     }
     int32_t slots = 0;
     boot->getNumberSlots(&slots);
@@ -184,7 +184,7 @@
     {
         const string emptySuffix = "";
         const auto result = boot->getSuffix(numSlots, &suffixStr);
-        ASSERT_TRUE(result.isOk());
+        ASSERT_TRUE(result.isOk()) << result;
         ASSERT_EQ(suffixStr, emptySuffix);
     }
 }
diff --git a/broadcastradio/1.0/vts/functional/Android.bp b/broadcastradio/1.0/vts/functional/Android.bp
index 623ff78..5a42fe4 100644
--- a/broadcastradio/1.0/vts/functional/Android.bp
+++ b/broadcastradio/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_aaos_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/broadcastradio/1.1/vts/functional/Android.bp b/broadcastradio/1.1/vts/functional/Android.bp
index 0fb4eb0..9d3db88 100644
--- a/broadcastradio/1.1/vts/functional/Android.bp
+++ b/broadcastradio/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_aaos_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/broadcastradio/2.0/vts/functional/Android.bp b/broadcastradio/2.0/vts/functional/Android.bp
index cb50c5e..03bec77 100644
--- a/broadcastradio/2.0/vts/functional/Android.bp
+++ b/broadcastradio/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_aaos_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/broadcastradio/aidl/default/fuzzer.cpp b/broadcastradio/aidl/default/fuzzer.cpp
index d535432..2492d47 100644
--- a/broadcastradio/aidl/default/fuzzer.cpp
+++ b/broadcastradio/aidl/default/fuzzer.cpp
@@ -24,6 +24,8 @@
 using ::android::fuzzService;
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    // TODO(b/183141167): need to rewrite 'dump' to avoid SIGPIPE.
+    signal(SIGPIPE, SIG_IGN);
     const VirtualRadio& amFmRadioMock = VirtualRadio::getAmFmRadio();
     std::shared_ptr<BroadcastRadio> amFmRadio =
             ::ndk::SharedRefBase::make<BroadcastRadio>(amFmRadioMock);
diff --git a/camera/common/aidl/Android.bp b/camera/common/aidl/Android.bp
index 8f7d19d..b59c92e 100644
--- a/camera/common/aidl/Android.bp
+++ b/camera/common/aidl/Android.bp
@@ -10,6 +10,7 @@
 
 aidl_interface {
     name: "android.hardware.camera.common",
+    host_supported: true,
     vendor_available: true,
     srcs: ["android/hardware/camera/common/*.aidl"],
     frozen: true,
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
index 184c16e..d92a409 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
@@ -109,7 +109,7 @@
 
     static const int kMaxProcessedStream = 2;
     static const int kMaxStallStream = 1;
-    static const uint32_t kMaxBytesPerPixel = 2;
+    static const uint32_t kMaxBytesPerPixel = 3;
 
     class OutputThread : public android::Thread {
     public:
diff --git a/camera/device/aidl/Android.bp b/camera/device/aidl/Android.bp
index 78aefac..291ed0d 100644
--- a/camera/device/aidl/Android.bp
+++ b/camera/device/aidl/Android.bp
@@ -10,16 +10,19 @@
 
 aidl_interface {
     name: "android.hardware.camera.device",
+    host_supported: true,
     vendor_available: true,
     srcs: ["android/hardware/camera/device/*.aidl"],
     frozen: true,
     stability: "vintf",
+    defaults: [
+        "android.hardware.graphics.common-latest",
+    ],
     imports: [
         "android.hardware.common-V2",
         "android.hardware.common.fmq-V1",
         "android.hardware.camera.common-V1",
         "android.hardware.camera.metadata-V3",
-        "android.hardware.graphics.common-V5",
     ],
     backend: {
         cpp: {
@@ -29,6 +32,9 @@
             sdk_version: "module_current",
             enabled: false,
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
@@ -38,7 +44,7 @@
                 "android.hardware.common.fmq-V1",
                 "android.hardware.camera.common-V1",
                 "android.hardware.camera.metadata-V1",
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
             ],
         },
         {
@@ -48,7 +54,7 @@
                 "android.hardware.common.fmq-V1",
                 "android.hardware.camera.common-V1",
                 "android.hardware.camera.metadata-V2",
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
             ],
         },
         {
@@ -58,7 +64,7 @@
                 "android.hardware.common.fmq-V1",
                 "android.hardware.camera.common-V1",
                 "android.hardware.camera.metadata-V3",
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
             ],
         },
 
diff --git a/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl b/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl
index 62a19cf..63ae320 100644
--- a/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl
+++ b/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl
@@ -575,6 +575,11 @@
      * This can be called at any point after 'processCaptureRequest' in response
      * to camera clients disabling an active repeating request.
      *
+     * Note: The frame number parameter is the latest possible frame number at which the
+     * ongoing repeating request will end. It is possible that the repeating request may end
+     * before the specified frame number due to reasons such as the camera client abandoning
+     * buffers, which is timing dependent.
+     *
      * Performance requirements:
      * The call must not be blocked for extensive periods and should be extremely lightweight. There
      * must be no frame rate degradation or frame jitter introduced.
diff --git a/camera/device/default/ExternalCameraDeviceSession.cpp b/camera/device/default/ExternalCameraDeviceSession.cpp
index 91196d4..abd5d7e 100644
--- a/camera/device/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/default/ExternalCameraDeviceSession.cpp
@@ -1136,6 +1136,11 @@
 
     uint32_t v4lBufferCount = (fps >= kDefaultFps) ? mCfg.numVideoBuffers : mCfg.numStillBuffers;
 
+    // Double the max lag in theory.
+    mMaxLagNs = v4lBufferCount * 1000000000LL * 2 / fps;
+    ALOGI("%s: set mMaxLagNs to %" PRIu64 " ns, v4lBufferCount %u", __FUNCTION__, mMaxLagNs,
+          v4lBufferCount);
+
     // VIDIOC_REQBUFS: create buffers
     v4l2_requestbuffers req_buffers{};
     req_buffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1232,40 +1237,67 @@
         }
     }
 
-    ATRACE_BEGIN("VIDIOC_DQBUF");
+    uint64_t lagNs = 0;
     v4l2_buffer buffer{};
-    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    buffer.memory = V4L2_MEMORY_MMAP;
-    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_DQBUF, &buffer)) < 0) {
-        ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno));
-        return ret;
-    }
-    ATRACE_END();
+    do {
+        ATRACE_BEGIN("VIDIOC_DQBUF");
+        buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        buffer.memory = V4L2_MEMORY_MMAP;
+        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_DQBUF, &buffer)) < 0) {
+            ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno));
+            return ret;
+        }
+        ATRACE_END();
 
-    if (buffer.index >= mV4L2BufferCount) {
-        ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index);
-        return ret;
-    }
+        if (buffer.index >= mV4L2BufferCount) {
+            ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index);
+            return ret;
+        }
 
-    if (buffer.flags & V4L2_BUF_FLAG_ERROR) {
-        ALOGE("%s: v4l2 buf error! buf flag 0x%x", __FUNCTION__, buffer.flags);
-        // TODO: try to dequeue again
-    }
+        if (buffer.flags & V4L2_BUF_FLAG_ERROR) {
+            ALOGE("%s: v4l2 buf error! buf flag 0x%x", __FUNCTION__, buffer.flags);
+            // TODO: try to dequeue again
+        }
 
-    if (buffer.bytesused > mMaxV4L2BufferSize) {
-        ALOGE("%s: v4l2 buffer bytes used: %u maximum %u", __FUNCTION__, buffer.bytesused,
-              mMaxV4L2BufferSize);
-        return ret;
-    }
+        if (buffer.bytesused > mMaxV4L2BufferSize) {
+            ALOGE("%s: v4l2 buffer bytes used: %u maximum %u", __FUNCTION__, buffer.bytesused,
+                  mMaxV4L2BufferSize);
+            return ret;
+        }
 
-    if (buffer.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) {
-        // Ideally we should also check for V4L2_BUF_FLAG_TSTAMP_SRC_SOE, but
-        // even V4L2_BUF_FLAG_TSTAMP_SRC_EOF is better than capture a timestamp now
-        *shutterTs = static_cast<nsecs_t>(buffer.timestamp.tv_sec) * 1000000000LL +
-                     buffer.timestamp.tv_usec * 1000LL;
-    } else {
-        *shutterTs = systemTime(SYSTEM_TIME_MONOTONIC);
-    }
+        nsecs_t curTimeNs = systemTime(SYSTEM_TIME_MONOTONIC);
+
+        if (buffer.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) {
+            // Ideally we should also check for V4L2_BUF_FLAG_TSTAMP_SRC_SOE, but
+            // even V4L2_BUF_FLAG_TSTAMP_SRC_EOF is better than capture a timestamp now
+            *shutterTs = static_cast<nsecs_t>(buffer.timestamp.tv_sec) * 1000000000LL +
+                         buffer.timestamp.tv_usec * 1000LL;
+        } else {
+            *shutterTs = curTimeNs;
+        }
+
+        // The tactic only takes effect on v4l2 buffers with flag V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC.
+        // Most USB cameras should have the feature.
+        if (curTimeNs < *shutterTs) {
+            lagNs = 0;
+            ALOGW("%s: should not happen, the monotonic clock has issue, shutterTs is in the "
+                  "future, curTimeNs %" PRId64 "  < "
+                  "shutterTs %" PRId64 "",
+                  __func__, curTimeNs, *shutterTs);
+        } else {
+            lagNs = curTimeNs - *shutterTs;
+        }
+
+        if (lagNs > mMaxLagNs) {
+            ALOGI("%s: drop too old buffer, index %d, lag %" PRIu64 " ns > max %" PRIu64 " ns", __FUNCTION__,
+                  buffer.index, lagNs, mMaxLagNs);
+            int retVal = ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer);
+            if (retVal) {
+                ALOGE("%s: unexpected VIDIOC_QBUF failed, retVal %d", __FUNCTION__, retVal);
+                return ret;
+            }
+        }
+    } while (lagNs > mMaxLagNs);
 
     {
         std::lock_guard<std::mutex> lk(mV4l2BufferLock);
diff --git a/camera/device/default/ExternalCameraDeviceSession.h b/camera/device/default/ExternalCameraDeviceSession.h
index 795b589..ed84931 100644
--- a/camera/device/default/ExternalCameraDeviceSession.h
+++ b/camera/device/default/ExternalCameraDeviceSession.h
@@ -122,7 +122,7 @@
 
     static const int kMaxProcessedStream = 2;
     static const int kMaxStallStream = 1;
-    static const uint32_t kMaxBytesPerPixel = 2;
+    static const uint32_t kMaxBytesPerPixel = 3;
 
     class BufferRequestThread : public SimpleThread {
       public:
@@ -382,6 +382,9 @@
     std::string mExifMake;
     std::string mExifModel;
     /* End of members not changed after initialize() */
+
+    // The max tolerant lag between the dequeued v4l2 buffer and current capture request.
+    uint64_t mMaxLagNs;
 };
 
 }  // namespace implementation
diff --git a/camera/metadata/aidl/Android.bp b/camera/metadata/aidl/Android.bp
index ae8ba14..a9c1a1a 100644
--- a/camera/metadata/aidl/Android.bp
+++ b/camera/metadata/aidl/Android.bp
@@ -10,6 +10,7 @@
 
 aidl_interface {
     name: "android.hardware.camera.metadata",
+    host_supported: true,
     vendor_available: true,
     srcs: ["android/hardware/camera/metadata/*.aidl"],
     frozen: true,
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 82666ae..49c8410 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -52,6 +52,7 @@
 #include <android/hardware/camera/provider/2.7/ICameraProvider.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <binder/MemoryHeapBase.h>
+#include <com_android_graphics_libgui_flags.h>
 #include <cutils/properties.h>
 #include <fmq/MessageQueue.h>
 #include <grallocusage/GrallocUsageConversion.h>
@@ -8714,16 +8715,25 @@
     ASSERT_NE(nullptr, bufferItemConsumer);
     ASSERT_NE(nullptr, bufferHandler);
 
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+    *bufferItemConsumer = new BufferItemConsumer(
+            GraphicBuffer::USAGE_HW_TEXTURE);  // Use GLConsumer default usage flags
+#else
     sp<IGraphicBufferProducer> producer;
     sp<IGraphicBufferConsumer> consumer;
     BufferQueue::createBufferQueue(&producer, &consumer);
     *bufferItemConsumer = new BufferItemConsumer(consumer,
             GraphicBuffer::USAGE_HW_TEXTURE); //Use GLConsumer default usage flags
+#endif  // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
     ASSERT_NE(nullptr, (*bufferItemConsumer).get());
     *bufferHandler = new BufferItemHander(*bufferItemConsumer);
     ASSERT_NE(nullptr, (*bufferHandler).get());
     (*bufferItemConsumer)->setFrameAvailableListener(*bufferHandler);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+    sp<Surface> surface = (*bufferItemConsumer)->getSurface();
+#else
     sp<Surface> surface = new Surface(producer);
+#endif  // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
     sp<PreviewWindowCb> previewCb = new PreviewWindowCb(surface);
 
     auto rc = device->setPreviewWindow(previewCb);
diff --git a/camera/provider/aidl/Android.bp b/camera/provider/aidl/Android.bp
index 38a8936..faad35a 100644
--- a/camera/provider/aidl/Android.bp
+++ b/camera/provider/aidl/Android.bp
@@ -10,6 +10,7 @@
 
 aidl_interface {
     name: "android.hardware.camera.provider",
+    host_supported: true,
     vendor_available: true,
     srcs: [
         "android/hardware/camera/provider/*.aidl",
@@ -27,6 +28,9 @@
         cpp: {
             enabled: false,
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
diff --git a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
index ad8d4c8..9fa4df2 100644
--- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
+++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
@@ -165,26 +165,21 @@
 
 // Validate the integrity of manual flash strength control metadata
 TEST_P(CameraAidlTest, validateManualFlashStrengthControlKeys) {
-    if (flags::camera_manual_flash_strength_control()) {
-        std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
-        for (const auto& name : cameraDeviceNames) {
-            ALOGI("validateManualFlashStrengthControlKeys: Testing camera device %s", name.c_str());
-            CameraMetadata meta;
-            std::shared_ptr<ICameraDevice> cameraDevice;
-            openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
-                    &cameraDevice /*out*/);
-            ndk::ScopedAStatus ret = cameraDevice->getCameraCharacteristics(&meta);
-            ASSERT_TRUE(ret.isOk());
-            const camera_metadata_t* staticMeta =
-                    reinterpret_cast<const camera_metadata_t*>(meta.metadata.data());
-            verifyManualFlashStrengthControlCharacteristics(staticMeta);
-            ret = mSession->close();
-            mSession = nullptr;
-            ASSERT_TRUE(ret.isOk());
-        }
-    } else {
-        ALOGI("validateManualFlashStrengthControlKeys: Test skipped.\n");
-        GTEST_SKIP();
+    std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    for (const auto& name : cameraDeviceNames) {
+        ALOGI("validateManualFlashStrengthControlKeys: Testing camera device %s", name.c_str());
+        CameraMetadata meta;
+        std::shared_ptr<ICameraDevice> cameraDevice;
+        openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
+                &cameraDevice /*out*/);
+        ndk::ScopedAStatus ret = cameraDevice->getCameraCharacteristics(&meta);
+        ASSERT_TRUE(ret.isOk());
+        const camera_metadata_t* staticMeta =
+                reinterpret_cast<const camera_metadata_t*>(meta.metadata.data());
+        verifyManualFlashStrengthControlCharacteristics(staticMeta);
+        ret = mSession->close();
+        mSession = nullptr;
+        ASSERT_TRUE(ret.isOk());
     }
 }
 
@@ -288,77 +283,70 @@
 }
 
 TEST_P(CameraAidlTest, getSessionCharacteristics) {
-    if (flags::feature_combination_query()) {
-        std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            std::shared_ptr<ICameraDevice> device;
-            ALOGI("getSessionCharacteristics: Testing camera device %s", name.c_str());
-            ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
-            ALOGI("getCameraDeviceInterface returns: %d:%d", ret.getExceptionCode(),
-                  ret.getServiceSpecificError());
-            ASSERT_TRUE(ret.isOk());
-            ASSERT_NE(device, nullptr);
+    for (const auto& name : cameraDeviceNames) {
+        std::shared_ptr<ICameraDevice> device;
+        ALOGI("getSessionCharacteristics: Testing camera device %s", name.c_str());
+        ndk::ScopedAStatus ret = mProvider->getCameraDeviceInterface(name, &device);
+        ALOGI("getCameraDeviceInterface returns: %d:%d", ret.getExceptionCode(),
+              ret.getServiceSpecificError());
+        ASSERT_TRUE(ret.isOk());
+        ASSERT_NE(device, nullptr);
 
-            int32_t interfaceVersion = -1;
-            ret = device->getInterfaceVersion(&interfaceVersion);
-            ASSERT_TRUE(ret.isOk());
-            bool supportSessionCharacteristics =
-                    (interfaceVersion >= CAMERA_DEVICE_API_MINOR_VERSION_3);
-            if (!supportSessionCharacteristics) {
-                continue;
-            }
-
-            CameraMetadata meta;
-            openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
-                                   &device /*out*/);
-
-            std::vector<AvailableStream> outputStreams;
-            camera_metadata_t* staticMeta =
-                    reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
-            outputStreams.clear();
-            ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
-            ASSERT_NE(0u, outputStreams.size());
-
-            AvailableStream sampleStream = outputStreams[0];
-
-            int32_t streamId = 0;
-            Stream stream = {streamId,
-                             StreamType::OUTPUT,
-                             sampleStream.width,
-                             sampleStream.height,
-                             static_cast<PixelFormat>(sampleStream.format),
-                             static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
-                                     GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
-                             Dataspace::UNKNOWN,
-                             StreamRotation::ROTATION_0,
-                             std::string(),
-                             /*bufferSize*/ 0,
-                             /*groupId*/ -1,
-                             {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
-                             RequestAvailableDynamicRangeProfilesMap::
-                                     ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
-
-            std::vector<Stream> streams = {stream};
-            StreamConfiguration config;
-            createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config);
-
-            CameraMetadata camera_chars;
-            ret = device->getCameraCharacteristics(&camera_chars);
-            ASSERT_TRUE(ret.isOk());
-
-            CameraMetadata session_chars;
-            ret = device->getSessionCharacteristics(config, &session_chars);
-            ASSERT_TRUE(ret.isOk());
-            verifySessionCharacteristics(session_chars, camera_chars);
-
-            ret = mSession->close();
-            mSession = nullptr;
-            ASSERT_TRUE(ret.isOk());
+        int32_t interfaceVersion = -1;
+        ret = device->getInterfaceVersion(&interfaceVersion);
+        ASSERT_TRUE(ret.isOk());
+        bool supportSessionCharacteristics =
+                (interfaceVersion >= CAMERA_DEVICE_API_MINOR_VERSION_3);
+        if (!supportSessionCharacteristics) {
+            continue;
         }
-    } else {
-        ALOGI("getSessionCharacteristics: Test skipped.\n");
-        GTEST_SKIP();
+
+        CameraMetadata meta;
+        openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/, &device /*out*/);
+
+        std::vector<AvailableStream> outputStreams;
+        camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
+        outputStreams.clear();
+        ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
+        ASSERT_NE(0u, outputStreams.size());
+
+        AvailableStream sampleStream = outputStreams[0];
+
+        int32_t streamId = 0;
+        Stream stream = {streamId,
+                         StreamType::OUTPUT,
+                         sampleStream.width,
+                         sampleStream.height,
+                         static_cast<PixelFormat>(sampleStream.format),
+                         static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
+                                 GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER),
+                         Dataspace::UNKNOWN,
+                         StreamRotation::ROTATION_0,
+                         std::string(),
+                         /*bufferSize*/ 0,
+                         /*groupId*/ -1,
+                         {SensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT},
+                         RequestAvailableDynamicRangeProfilesMap::
+                                 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD};
+
+        std::vector<Stream> streams = {stream};
+        StreamConfiguration config;
+        createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE, &config);
+
+        CameraMetadata camera_chars;
+        ret = device->getCameraCharacteristics(&camera_chars);
+        ASSERT_TRUE(ret.isOk());
+
+        CameraMetadata session_chars;
+        ret = device->getSessionCharacteristics(config, &session_chars);
+        ASSERT_TRUE(ret.isOk());
+        verifySessionCharacteristics(session_chars, camera_chars);
+
+        ret = mSession->close();
+        mSession = nullptr;
+        ASSERT_TRUE(ret.isOk());
     }
 }
 
@@ -615,19 +603,17 @@
                 ASSERT_EQ(0u, rawMetadata.metadata.size());
             }
 
-            if (flags::feature_combination_query()) {
-                if (supportFeatureCombinationQuery) {
-                    CameraMetadata rawMetadata2;
-                    ndk::ScopedAStatus ret2 =
-                            device->constructDefaultRequestSettings(reqTemplate, &rawMetadata2);
+            if (supportFeatureCombinationQuery) {
+                CameraMetadata rawMetadata2;
+                ndk::ScopedAStatus ret2 =
+                        device->constructDefaultRequestSettings(reqTemplate, &rawMetadata2);
 
-                    ASSERT_EQ(ret.isOk(), ret2.isOk());
-                    ASSERT_EQ(ret.getStatus(), ret2.getStatus());
+                ASSERT_EQ(ret.isOk(), ret2.isOk());
+                ASSERT_EQ(ret.getStatus(), ret2.getStatus());
 
-                    ASSERT_EQ(rawMetadata.metadata.size(), rawMetadata2.metadata.size());
-                    if (ret2.isOk()) {
-                        validateDefaultRequestMetadata(reqTemplate, rawMetadata2);
-                    }
+                ASSERT_EQ(rawMetadata.metadata.size(), rawMetadata2.metadata.size());
+                if (ret2.isOk()) {
+                    validateDefaultRequestMetadata(reqTemplate, rawMetadata2);
                 }
             }
         }
diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp
index f905011..6ecd451 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -1920,28 +1920,22 @@
         ASSERT_TRUE(ret.isOk());
         ASSERT_EQ(expectedStatus, streamCombinationSupported);
 
-        if (flags::feature_combination_query()) {
-            int32_t interfaceVersion;
-            ret = device->getInterfaceVersion(&interfaceVersion);
+        int32_t interfaceVersion;
+        ret = device->getInterfaceVersion(&interfaceVersion);
+        ASSERT_TRUE(ret.isOk());
+        bool supportFeatureCombinationQuery =
+                (interfaceVersion >= CAMERA_DEVICE_API_MINOR_VERSION_3);
+        if (supportFeatureCombinationQuery) {
+            ret = device->isStreamCombinationWithSettingsSupported(config,
+                                                                   &streamCombinationSupported);
             ASSERT_TRUE(ret.isOk());
-            bool supportFeatureCombinationQuery =
-                    (interfaceVersion >= CAMERA_DEVICE_API_MINOR_VERSION_3);
-            if (supportFeatureCombinationQuery) {
-                ret = device->isStreamCombinationWithSettingsSupported(config,
-                                                                       &streamCombinationSupported);
-                ASSERT_TRUE(ret.isOk());
-                ASSERT_EQ(expectedStatus, streamCombinationSupported);
-            }
+            ASSERT_EQ(expectedStatus, streamCombinationSupported);
         }
     }
 }
 
 void CameraAidlTest::verifySessionCharacteristics(const CameraMetadata& session_chars,
                                                   const CameraMetadata& camera_chars) {
-    if (!flags::feature_combination_query()) {
-        return;
-    }
-
     const camera_metadata_t* session_metadata =
             reinterpret_cast<const camera_metadata_t*>(session_chars.metadata.data());
 
diff --git a/cas/1.0/vts/functional/Android.bp b/cas/1.0/vts/functional/Android.bp
index 6d06cab..1817371 100644
--- a/cas/1.0/vts/functional/Android.bp
+++ b/cas/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_tv_os",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/cas/1.1/vts/functional/Android.bp b/cas/1.1/vts/functional/Android.bp
index a598554..f95f9b3 100644
--- a/cas/1.1/vts/functional/Android.bp
+++ b/cas/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_tv_os",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/cas/1.2/default/Android.bp b/cas/1.2/default/Android.bp
index 38561fd..5bc8bad 100644
--- a/cas/1.2/default/Android.bp
+++ b/cas/1.2/default/Android.bp
@@ -46,6 +46,7 @@
     vintf_fragments: ["android.hardware.cas@1.2-service.xml"],
     defaults: ["cas_service_defaults@1.2"],
     init_rc: ["android.hardware.cas@1.2-service.rc"],
+    overrides: ["com.android.hardware.cas"],
 }
 
 cc_binary {
diff --git a/cas/1.2/vts/functional/Android.bp b/cas/1.2/vts/functional/Android.bp
index 21f791b..3b1cfb1 100644
--- a/cas/1.2/vts/functional/Android.bp
+++ b/cas/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_tv_os",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/cas/aidl/vts/functional/Android.bp b/cas/aidl/vts/functional/Android.bp
index 295ae7c..390c713 100644
--- a/cas/aidl/vts/functional/Android.bp
+++ b/cas/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_codec_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index 904a3d9..0ce52e7 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -26,7 +26,7 @@
             ],
         },
         cpp: {
-            enabled: false,
+            enabled: true,
         },
         ndk: {
             apex_available: [
diff --git a/common/fmq/aidl/Android.bp b/common/fmq/aidl/Android.bp
index 9c1b45d..7fb6368 100644
--- a/common/fmq/aidl/Android.bp
+++ b/common/fmq/aidl/Android.bp
@@ -28,15 +28,13 @@
             sdk_version: "module_current",
         },
         cpp: {
-            // FMQ will not be supported in the cpp backend because the parcelables
-            // are not stable enough for use in shared memory
-            enabled: false,
+            // FMQ is only supported for PODs with the cpp backend
+            enabled: true,
         },
         ndk: {
             apex_available: [
                 "//apex_available:platform",
-                "com.android.btservices",
-                "com.android.media.swcodec",
+                "//apex_available:anyapex",
             ],
             min_sdk_version: "29",
         },
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index ad42015..19f4839 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -21,6 +21,65 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+// Device framework compatibility matrix (common to all FCM versions)
+// Reference: https://source.android.com/docs/core/architecture/vintf/comp-matrices
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.device.xml",
+    stem: "compatibility_matrix.device.xml",
+    type: "device_fcm",
+}
+
+// Phony target that installs all system compatibility matrix files
+SYSTEM_MATRIX_DEPS = [
+    "framework_compatibility_matrix.5.xml",
+    "framework_compatibility_matrix.6.xml",
+    "framework_compatibility_matrix.7.xml",
+    "framework_compatibility_matrix.8.xml",
+    "framework_compatibility_matrix.202404.xml",
+    "framework_compatibility_matrix.device.xml",
+]
+
+phony {
+    name: "system_compatibility_matrix.xml",
+    required: SYSTEM_MATRIX_DEPS,
+    product_variables: {
+        release_aidl_use_unfrozen: {
+            required: [
+                "framework_compatibility_matrix.202504.xml",
+            ],
+        },
+    },
+}
+
+// Product Compatibility Matrix
+vintf_compatibility_matrix {
+    name: "product_compatibility_matrix.xml",
+    stem: "compatibility_matrix.xml",
+    product_specific: true,
+    type: "product_fcm",
+}
+
+// Phony target that installs all framework compatibility matrix files (system + product)
+FRAMEWORK_MATRIX_DEPS = SYSTEM_MATRIX_DEPS + ["product_compatibility_matrix.xml"]
+
+phony {
+    name: "framework_compatibility_matrix.xml",
+    required: FRAMEWORK_MATRIX_DEPS,
+    product_variables: {
+        release_aidl_use_unfrozen: {
+            required: [
+                "framework_compatibility_matrix.202504.xml",
+            ],
+        },
+    },
+}
+
+////////////////////////////////////////////
+// AUTO GENERATED MODULES
+// DO NOT ADD MORE MODULES BELOW THIS LINE
+////////////////////////////////////////////
+
+// System compatibility matrices
 vintf_compatibility_matrix {
     name: "framework_compatibility_matrix.5.xml",
     stem: "compatibility_matrix.5.xml",
@@ -88,29 +147,6 @@
     stem: "compatibility_matrix.202504.xml",
     srcs: ["compatibility_matrix.202504.xml"],
     kernel_configs: [
-        "kernel_config_w_6.next",
+        "kernel_config_b_6.12",
     ],
-
-}
-
-// Phony target that installs all system compatibility matrix files
-SYSTEM_MATRIX_DEPS = [
-    "framework_compatibility_matrix.5.xml",
-    "framework_compatibility_matrix.6.xml",
-    "framework_compatibility_matrix.7.xml",
-    "framework_compatibility_matrix.8.xml",
-    "framework_compatibility_matrix.202404.xml",
-    "framework_compatibility_matrix.device.xml",
-]
-
-phony {
-    name: "system_compatibility_matrix.xml",
-    required: SYSTEM_MATRIX_DEPS,
-    product_variables: {
-        release_aidl_use_unfrozen: {
-            required: [
-                "framework_compatibility_matrix.202504.xml",
-            ],
-        },
-    },
 }
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
deleted file mode 100644
index 338c075..0000000
--- a/compatibility_matrices/Android.mk
+++ /dev/null
@@ -1,134 +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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-BUILD_FRAMEWORK_COMPATIBILITY_MATRIX := $(LOCAL_PATH)/compatibility_matrix.mk
-my_empty_manifest := $(LOCAL_PATH)/manifest.empty.xml
-
-# System Compatibility Matrix (common to all FCM versions)
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/clear_vars.mk
-LOCAL_MODULE := framework_compatibility_matrix.device.xml
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE
-LOCAL_MODULE_STEM := compatibility_matrix.device.xml
-# define LOCAL_MODULE_CLASS for local-generated-sources-dir.
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_RELATIVE_PATH := vintf
-
-ifndef DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
-LOCAL_SRC_FILES := compatibility_matrix.empty.xml
-else
-
-# DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE specifies absolute paths
-LOCAL_GENERATED_SOURCES := $(DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE)
-
-# Enforce that DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE does not specify required HALs
-# by checking it against an empty manifest. But the empty manifest needs to contain
-# BOARD_SEPOLICY_VERS to be compatible with DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE.
-my_gen_check_manifest := $(local-generated-sources-dir)/manifest.check.xml
-$(my_gen_check_manifest): PRIVATE_SRC_FILE := $(my_empty_manifest)
-$(my_gen_check_manifest): $(my_empty_manifest) $(HOST_OUT_EXECUTABLES)/assemble_vintf
-	BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) \
-	VINTF_IGNORE_TARGET_FCM_VERSION=true \
-		$(HOST_OUT_EXECUTABLES)/assemble_vintf -i $(PRIVATE_SRC_FILE) -o $@
-
-LOCAL_GEN_FILE_DEPENDENCIES += $(my_gen_check_manifest)
-LOCAL_ASSEMBLE_VINTF_FLAGS += -c "$(my_gen_check_manifest)"
-
-my_gen_check_manifest :=
-
-endif # DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
-
-# TODO(b/296875906): use POLICYVERS from Soong
-POLICYVERS ?= 30
-
-LOCAL_ADD_VBMETA_VERSION := true
-LOCAL_ASSEMBLE_VINTF_ENV_VARS := \
-    POLICYVERS \
-    PLATFORM_SEPOLICY_VERSION \
-    PLATFORM_SEPOLICY_COMPAT_VERSIONS
-
-include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
-
-# Product Compatibility Matrix
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/clear_vars.mk
-LOCAL_MODULE := product_compatibility_matrix.xml
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE
-
-ifndef DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
-my_framework_matrix_deps :=
-include $(BUILD_PHONY_PACKAGE)
-else # DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
-
-LOCAL_MODULE_STEM := compatibility_matrix.xml
-LOCAL_PRODUCT_MODULE := true
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_RELATIVE_PATH := vintf
-
-# DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE specifies absolute paths
-LOCAL_GENERATED_SOURCES := $(DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE)
-
-# Enforce that DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE does not specify required HALs
-# by checking it against an empty manifest.
-LOCAL_GEN_FILE_DEPENDENCIES += $(my_empty_manifest)
-LOCAL_ASSEMBLE_VINTF_FLAGS += -c "$(my_empty_manifest)"
-
-my_framework_matrix_deps := $(LOCAL_MODULE)
-
-include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
-
-endif # DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
-
-my_system_matrix_deps := \
-    framework_compatibility_matrix.5.xml \
-    framework_compatibility_matrix.6.xml \
-    framework_compatibility_matrix.7.xml \
-    framework_compatibility_matrix.8.xml \
-    framework_compatibility_matrix.202404.xml \
-    framework_compatibility_matrix.device.xml \
-
-# Only allow the use of the unreleased compatibility matrix when we can use unfrozen
-# interfaces (in the `next` release configuration).
-ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
-my_system_matrix_deps += \
-    framework_compatibility_matrix.202504.xml \
-
-endif
-
-my_framework_matrix_deps += \
-    $(my_system_matrix_deps)
-
-# Phony target that installs all framework compatibility matrix files (system + product)
-include $(CLEAR_VARS)
-LOCAL_MODULE := framework_compatibility_matrix.xml
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE
-LOCAL_REQUIRED_MODULES := $(my_framework_matrix_deps)
-include $(BUILD_PHONY_PACKAGE)
-
-my_system_matrix_deps :=
-my_framework_matrix_deps :=
-my_empty_manifest :=
-BUILD_FRAMEWORK_COMPATIBILITY_MATRIX :=
diff --git a/compatibility_matrices/build/Android.bp b/compatibility_matrices/build/Android.bp
index 79ef36d..6011fcc 100644
--- a/compatibility_matrices/build/Android.bp
+++ b/compatibility_matrices/build/Android.bp
@@ -30,6 +30,7 @@
         "kernel-config-soong-rules",
         "soong",
         "soong-android",
+        "soong-selinux",
     ],
     srcs: [
         "vintf_compatibility_matrix.go",
diff --git a/compatibility_matrices/build/vintf_compatibility_matrix.go b/compatibility_matrices/build/vintf_compatibility_matrix.go
index c72cbde..b8f2a14 100644
--- a/compatibility_matrices/build/vintf_compatibility_matrix.go
+++ b/compatibility_matrices/build/vintf_compatibility_matrix.go
@@ -24,6 +24,7 @@
 
 	"android/soong/android"
 	"android/soong/kernel/configs"
+	"android/soong/selinux"
 )
 
 type dependencyTag struct {
@@ -35,10 +36,10 @@
 	pctx = android.NewPackageContext("android/vintf")
 
 	assembleVintfRule = pctx.AndroidStaticRule("assemble_vintf", blueprint.RuleParams{
-		Command:     `${assembleVintfCmd} -i ${inputs} -o ${out}`,
-		CommandDeps: []string{"${assembleVintfCmd}"},
+		Command:     `${assembleVintfEnv} ${assembleVintfCmd} -i ${inputs} -o ${out} ${extraArgs}`,
+		CommandDeps: []string{"${assembleVintfCmd}", "${AvbToolCmd}"},
 		Description: "assemble_vintf -i ${inputs}",
-	}, "inputs")
+	}, "inputs", "extraArgs", "assembleVintfEnv")
 
 	xmllintXsd = pctx.AndroidStaticRule("xmllint-xsd", blueprint.RuleParams{
 		Command:     `$XmlLintCmd --quiet --schema $xsd $in > /dev/null && touch -a $out`,
@@ -52,7 +53,11 @@
 )
 
 const (
-	relpath = "vintf"
+	relpath                  = "vintf"
+	emptyManifest            = "hardware/interfaces/compatibility_matrices/manifest.empty.xml"
+	compatibilityEmptyMatrix = "hardware/interfaces/compatibility_matrices/compatibility_matrix.empty.xml"
+	deviceFcmType            = "device_fcm"
+	productFcmType           = "product_fcm"
 )
 
 type vintfCompatibilityMatrixProperties struct {
@@ -64,6 +69,9 @@
 
 	// list of kernel_config modules to be combined to final output
 	Kernel_configs []string
+
+	// Type of the FCM type, the allowed type are device_fcm and product_fcm and it should only be used under hardware/interfaces/compatibility_matrices
+	Type *string
 }
 
 type vintfCompatibilityMatrixRule struct {
@@ -72,11 +80,13 @@
 
 	genFile                android.WritablePath
 	additionalDependencies android.WritablePaths
+	phonyOnly              bool
 }
 
 func init() {
 	pctx.HostBinToolVariable("assembleVintfCmd", "assemble_vintf")
 	pctx.HostBinToolVariable("XmlLintCmd", "xmllint")
+	pctx.HostBinToolVariable("AvbToolCmd", "avbtool")
 	android.RegisterModuleType("vintf_compatibility_matrix", vintfCompatibilityMatrixFactory)
 }
 
@@ -131,6 +141,20 @@
 }
 
 func (g *vintfCompatibilityMatrixRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	// Types attribute only allow `device_fcm` or `product_fcm` if set and only restricted it being used under
+	// `hardware/interfaces/compatibility_matrices` to prevent accidental external usages.
+	matrixType := proptools.String(g.properties.Type)
+	if matrixType != "" {
+		if matrixType != deviceFcmType && matrixType != productFcmType {
+			panic(fmt.Errorf("The attribute 'type' value must be either 'device_fcm' or 'product_fcm' if set!"))
+		}
+		if !strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "hardware/interfaces/compatibility_matrices") {
+			panic(fmt.Errorf("Attribute type can only be set for module under `hardware/interfaces/compatibility_matrices`!"))
+		}
+		if (len(g.properties.Srcs) + len(g.properties.Kernel_configs)) > 0 {
+			panic(fmt.Errorf("Attribute 'type' and 'srcs' or 'kernel_configs' should not set simultaneously! To update inputs for this rule, edit vintf_compatibility_matrix.go directly."))
+		}
+	}
 
 	outputFilename := proptools.String(g.properties.Stem)
 	if outputFilename == "" {
@@ -158,15 +182,72 @@
 		}
 	})
 
+	// For product_compatibility_matrix.xml the source is from the product configuration
+	// DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE.
+	extraArgs := []string{}
+	if matrixType == productFcmType {
+		productMatrixs := android.PathsForSource(ctx, ctx.Config().DeviceProductCompatibilityMatrixFile())
+		if len(productMatrixs) > 0 {
+			inputPaths = append(inputPaths, productMatrixs...)
+			extraArgs = append(extraArgs, "-c", android.PathForSource(ctx, emptyManifest).String())
+		} else {
+			// For product_fcm, if DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE not set, treat it as a phony target without any output generated.
+			g.phonyOnly = true
+			return
+		}
+	}
+
+	// For framework_compatibility_matrix.device.xml the source may come from the product configuration
+	// DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE or use compatibilityEmptyMatrix if not set. We can't
+	// use a phony target because we still need to install framework_compatibility_matrix.device.xml to
+	// include sepolicy versions.
+	frameworkRuleImplicits := []android.Path{}
+
+	if matrixType == deviceFcmType {
+		frameworkMatrixs := android.PathsForSource(ctx, ctx.Config().DeviceFrameworkCompatibilityMatrixFile())
+		if len(frameworkMatrixs) > 0 {
+			inputPaths = append(inputPaths, frameworkMatrixs...)
+
+			// Generate BuildAction for generating the check manifest.
+			emptyManifestPath := android.PathForSource(ctx, emptyManifest)
+			genCheckManifest := android.PathForModuleGen(ctx, "manifest.check.xml")
+			checkManifestInputs := []android.Path{emptyManifestPath}
+			genCheckManifestEnvs := []string{
+				"BOARD_SEPOLICY_VERS=" + ctx.DeviceConfig().BoardSepolicyVers(),
+				"VINTF_IGNORE_TARGET_FCM_VERSION=true",
+			}
+
+			ctx.Build(pctx, android.BuildParams{
+				Rule:        assembleVintfRule,
+				Description: "Framework Check Manifest",
+				Implicits:   checkManifestInputs,
+				Output:      genCheckManifest,
+				Args: map[string]string{
+					"inputs":           android.PathForSource(ctx, emptyManifest).String(),
+					"extraArgs":        "",
+					"assembleVintfEnv": strings.Join(genCheckManifestEnvs, " "),
+				},
+			})
+
+			frameworkRuleImplicits = append(frameworkRuleImplicits, genCheckManifest)
+			extraArgs = append(extraArgs, "-c", genCheckManifest.String())
+		} else {
+			inputPaths = append(inputPaths, android.PathForSource(ctx, compatibilityEmptyMatrix))
+		}
+	}
+
 	g.genFile = android.PathForModuleGen(ctx, outputFilename)
+	frameworkRuleImplicits = append(frameworkRuleImplicits, inputPaths...)
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        assembleVintfRule,
 		Description: "Framework Compatibility Matrix",
-		Implicits:   inputPaths,
+		Implicits:   frameworkRuleImplicits,
 		Output:      g.genFile,
 		Args: map[string]string{
-			"inputs": strings.Join(inputPaths.Strings(), ":"),
+			"inputs":           strings.Join(inputPaths.Strings(), ":"),
+			"extraArgs":        strings.Join(extraArgs, " "),
+			"assembleVintfEnv": g.getAssembleVintfEnv(ctx),
 		},
 	})
 	g.generateValidateBuildAction(ctx, g.genFile, schema.Path())
@@ -174,7 +255,39 @@
 	ctx.InstallFile(android.PathForModuleInstall(ctx, "etc", relpath), outputFilename, g.genFile)
 }
 
+func (g *vintfCompatibilityMatrixRule) getAssembleVintfEnv(ctx android.ModuleContext) string {
+	if proptools.String(g.properties.Type) == deviceFcmType {
+		assembleVintfEnvs := []string{
+			// POLICYVERS defined in system/sepolicy/build/soong/policy.go
+			fmt.Sprintf("POLICYVERS=%d", selinux.PolicyVers),
+			fmt.Sprintf("PLATFORM_SEPOLICY_VERSION=%s", ctx.DeviceConfig().PlatformSepolicyVersion()),
+			fmt.Sprintf("PLATFORM_SEPOLICY_COMPAT_VERSIONS=\"%s\"", strings.Join(ctx.DeviceConfig().PlatformSepolicyCompatVersions(), " ")),
+		}
+
+		if ctx.Config().BoardAvbEnable() {
+			assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("FRAMEWORK_VBMETA_VERSION=\"$$(${AvbToolCmd} add_hashtree_footer --print_required_libavb_version %s)\"", strings.Join(ctx.Config().BoardAvbSystemAddHashtreeFooterArgs(), " ")))
+		} else {
+			assembleVintfEnvs = append(assembleVintfEnvs, "FRAMEWORK_VBMETA_VERSION=\"0.0\"")
+		}
+
+		return strings.Join(assembleVintfEnvs, " ")
+	}
+
+	return ""
+}
+
 func (g *vintfCompatibilityMatrixRule) AndroidMk() android.AndroidMkData {
+	if g.phonyOnly {
+		return android.AndroidMkData{
+			Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+				fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)", " # vintf.vintf_compatibility_matrix")
+				fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
+				fmt.Fprintln(w, "LOCAL_MODULE :=", name)
+				fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
+			},
+		}
+	}
+
 	return android.AndroidMkData{
 		Class:      "ETC",
 		OutputFile: android.OptionalPathForPath(g.genFile),
diff --git a/compatibility_matrices/bump.py b/compatibility_matrices/bump.py
index a5a453b..91f58d4 100755
--- a/compatibility_matrices/bump.py
+++ b/compatibility_matrices/bump.py
@@ -21,7 +21,7 @@
 import argparse
 import os
 import pathlib
-import shutil
+import re
 import subprocess
 import textwrap
 
@@ -44,6 +44,8 @@
 
         self.current_level = cmdline_args.current_level
         self.current_letter = cmdline_args.current_letter
+        self.current_version = cmdline_args.platform_version
+        self.next_version = cmdline_args.next_platform_version
         self.current_module_name = f"framework_compatibility_matrix.{self.current_level}.xml"
         self.current_xml = self.interfaces_dir / f"compatibility_matrices/compatibility_matrix.{self.current_level}.xml"
         self.device_module_name = "framework_compatibility_matrix.device.xml"
@@ -57,13 +59,13 @@
         self.bump_kernel_configs()
         self.copy_matrix()
         self.edit_android_bp()
-        self.edit_android_mk()
+        self.bump_libvintf()
 
     def bump_kernel_configs(self):
         check_call([
             self.top / "kernel/configs/tools/bump.py",
-            self.current_letter,
-            self.next_letter,
+            self.current_letter.lower(),
+            self.next_letter.lower(),
         ])
 
     def copy_matrix(self):
@@ -87,7 +89,7 @@
         next_kernel_configs = check_output(
             """grep -rh name: | sed -E 's/^.*"(.*)".*/\\1/g'""",
             cwd=self.top / "kernel/configs" /
-            self.next_letter,
+            self.next_letter.lower(),
             text=True,
             shell=True,
         ).splitlines()
@@ -109,40 +111,89 @@
             "kernel_configs", "-a", " ".join(next_kernel_configs), android_bp
         ])
 
-    def edit_android_mk(self):
-        android_mk = self.interfaces_dir / "compatibility_matrices/Android.mk"
+        # update the SYSTEM_MATRIX_DEPS variable and the phony module's
+        # product_variables entry.
         lines = []
-        with open(android_mk) as f:
-            if self.next_module_name in f.read():
-                return
-            f.seek(0)
+        with open(android_bp) as f:
             for line in f:
-              if f"    {self.device_module_name} \\\n" in line:
-                  lines.append(f"    {self.current_module_name} \\\n")
+              if f"    \"{self.device_module_name}\",\n" in line:
+                  lines.append(f"    \"{self.current_module_name}\",\n")
 
-              if self.current_module_name in line:
-                  lines.append(f"    {self.next_module_name} \\\n")
+              if f"                \"{self.current_module_name}\",\n" in line:
+                  lines.append(f"                \"{self.next_module_name}\",\n")
               else:
                   lines.append(line)
 
-        with open(android_mk, "w") as f:
+        with open(android_bp, "w") as f:
             f.write("".join(lines))
 
+    def bump_libvintf(self):
+        if not self.current_version:
+            print("Skip libvintf update...")
+            return
+        try:
+            check_call(["grep", "-h",
+                        f"{self.next_letter.upper()} = {self.next_level}",
+                        f"{self.top}/system/libvintf/include/vintf/Level.h"])
+        except subprocess.CalledProcessError:
+            print("Adding new API level to libvintf")
+            add_lines_above(f"{self.top}/system/libvintf/analyze_matrix/analyze_matrix.cpp",
+                            "        case Level::UNSPECIFIED:",
+                            textwrap.indent(textwrap.dedent(f"""\
+                                    case Level::{self.next_letter.upper()}:
+                                        return "Android {self.next_version} ({self.next_letter.upper()})";"""),
+                            "    "*2))
+            add_lines_above(f"{self.top}/system/libvintf/include/vintf/Level.h",
+                            "    // To add new values:",
+                            f"    {self.next_letter.upper()} = {self.next_level},")
+            add_lines_above(f"{self.top}/system/libvintf/include/vintf/Level.h",
+                            "        Level::UNSPECIFIED,",
+                            f"        Level::{self.next_letter.upper()},")
+            add_lines_above(f"{self.top}/system/libvintf/RuntimeInfo.cpp",
+                            "            // Add more levels above this line.",
+                            textwrap.indent(textwrap.dedent(f"""\
+                                        case {self.next_version}: {{
+                                            ret = Level::{self.next_letter.upper()};
+                                        }} break;"""),
+                            "    "*3))
+
+
+def add_lines_above(file, pattern, lines):
+    with open(file, 'r+') as f:
+        text = f.read()
+        split_text = re.split(rf"\n{pattern}\n", text)
+        if len(split_text) != 2:
+            # Only one pattern must be found, otherwise the source must be
+            # changed unexpectedly.
+            raise Exception(
+                f'Pattern "{pattern}" not found or multiple patterns found in {file}')
+        f.seek(0)
+        f.write(f"\n{lines}\n{pattern}\n".join(split_text))
+        f.truncate()
+
 
 def main():
     parser = argparse.ArgumentParser(description=__doc__)
     parser.add_argument("current_level",
                         type=str,
-                        help="VINTF level of the current version (e.g. 9)")
+                        help="VINTF level of the current version (e.g. 202404)")
     parser.add_argument("next_level",
                         type=str,
-                        help="VINTF level of the next version (e.g. 10)")
+                        help="VINTF level of the next version (e.g. 202504)")
     parser.add_argument("current_letter",
                         type=str,
-                        help="Letter of the API level of the current version (e.g. v)")
+                        help="Letter of the API level of the current version (e.g. b)")
     parser.add_argument("next_letter",
                         type=str,
-                        help="Letter of the API level of the next version (e.g. w)")
+                        help="Letter of the API level of the next version (e.g. c)")
+    parser.add_argument("platform_version",
+                        type=str,
+                        nargs="?",
+                        help="Current Android release version number (e.g. 16)")
+    parser.add_argument("next_platform_version",
+                        type=str,
+                        nargs="?",
+                        help="Next Android release version number number (e.g. 17)")
     cmdline_args = parser.parse_args()
 
     Bump(cmdline_args).run()
diff --git a/compatibility_matrices/clear_vars.mk b/compatibility_matrices/clear_vars.mk
index 0e53885..3c62377 100644
--- a/compatibility_matrices/clear_vars.mk
+++ b/compatibility_matrices/clear_vars.mk
@@ -16,10 +16,6 @@
 
 # Clear input variables to BUILD_FRAMEWORK_COMPATIBILITY_MATRIX
 LOCAL_ADD_VBMETA_VERSION :=
-LOCAL_ADD_VBMETA_VERSION_OVERRIDE :=
 LOCAL_ASSEMBLE_VINTF_ENV_VARS :=
-LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE :=
-LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE :=
 LOCAL_ASSEMBLE_VINTF_FLAGS :=
-LOCAL_KERNEL_CONFIG_DATA_PATHS :=
 LOCAL_GEN_FILE_DEPENDENCIES :=
diff --git a/compatibility_matrices/compatibility_matrix.202404.xml b/compatibility_matrices/compatibility_matrix.202404.xml
index 9ea476a..aa6b8f0 100644
--- a/compatibility_matrices/compatibility_matrix.202404.xml
+++ b/compatibility_matrices/compatibility_matrix.202404.xml
@@ -28,7 +28,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.audio.sounddose</name>
-        <version>1-2</version>
+        <version>1-3</version>
         <interface>
             <name>ISoundDoseFactory</name>
             <instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.202504.xml b/compatibility_matrices/compatibility_matrix.202504.xml
index ee62163..8338e13 100644
--- a/compatibility_matrices/compatibility_matrix.202504.xml
+++ b/compatibility_matrices/compatibility_matrix.202504.xml
@@ -26,14 +26,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl">
-        <name>android.hardware.audio.sounddose</name>
-        <version>1-3</version>
-        <interface>
-            <name>ISoundDoseFactory</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" updatable-via-apex="true">
          <name>android.hardware.authsecret</name>
          <version>1</version>
@@ -140,13 +132,21 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.bluetooth.ranging</name>
-        <version>1</version>
+        <version>1-2</version>
         <interface>
             <name>IBluetoothChannelSounding</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="aidl">
+        <name>android.hardware.bluetooth.socket</name>
+        <version>1</version>
+        <interface>
+            <name>IBluetoothSocket</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl">
         <name>android.hardware.bluetooth.finder</name>
         <version>1</version>
         <interface>
@@ -202,7 +202,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.contexthub</name>
-        <version>3</version>
+        <version>3-4</version>
         <interface>
             <name>IContextHub</name>
             <instance>default</instance>
@@ -249,7 +249,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.graphics.composer3</name>
-        <version>3</version>
+        <version>4</version>
         <interface>
             <name>IComposer</name>
             <instance>default</instance>
@@ -312,7 +312,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.security.secretkeeper</name>
-        <version>1</version>
+        <version>1-2</version>
         <interface>
             <name>ISecretkeeper</name>
             <instance>default</instance>
@@ -321,7 +321,7 @@
     </hal>
     <hal format="aidl" updatable-via-apex="true">
         <name>android.hardware.security.keymint</name>
-        <version>1-3</version>
+        <version>1-4</version>
         <interface>
             <name>IKeyMintDevice</name>
             <instance>default</instance>
@@ -372,6 +372,7 @@
     </hal>
     <hal format="aidl" updatable-via-apex="true">
         <name>android.hardware.nfc</name>
+        <version>1-2</version>
         <interface>
             <name>INfc</name>
             <instance>default</instance>
@@ -395,7 +396,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.radio.config</name>
-        <version>3</version>
+        <version>3-4</version>
         <interface>
             <name>IRadioConfig</name>
             <instance>default</instance>
@@ -403,7 +404,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.radio.data</name>
-        <version>3</version>
+        <version>3-4</version>
         <interface>
             <name>IRadioData</name>
             <instance>slot1</instance>
@@ -413,7 +414,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.radio.messaging</name>
-        <version>3</version>
+        <version>3-4</version>
         <interface>
             <name>IRadioMessaging</name>
             <instance>slot1</instance>
@@ -423,7 +424,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.radio.modem</name>
-        <version>3</version>
+        <version>3-4</version>
         <interface>
             <name>IRadioModem</name>
             <instance>slot1</instance>
@@ -433,7 +434,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.radio.network</name>
-        <version>3</version>
+        <version>3-4</version>
         <interface>
             <name>IRadioNetwork</name>
             <instance>slot1</instance>
@@ -443,7 +444,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.radio.sim</name>
-        <version>3</version>
+        <version>3-4</version>
         <interface>
             <name>IRadioSim</name>
             <instance>slot1</instance>
@@ -463,7 +464,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.radio.voice</name>
-        <version>3</version>
+        <version>3-4</version>
         <interface>
             <name>IRadioVoice</name>
             <instance>slot1</instance>
@@ -473,7 +474,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.radio.ims</name>
-        <version>2</version>
+        <version>2-3</version>
         <interface>
             <name>IRadioIms</name>
             <instance>slot1</instance>
@@ -483,7 +484,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.radio.ims.media</name>
-        <version>2</version>
+        <version>2-3</version>
         <interface>
             <name>IImsMedia</name>
             <instance>default</instance>
@@ -514,6 +515,14 @@
             <instance>nonsecure</instance>
         </interface>
     </hal>
+    <hal format="aidl">
+        <name>android.hardware.security.see.hwcrypto</name>
+        <version>1</version>
+        <interface>
+            <name>IHwCryptoKey</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="aidl" updatable-via-apex="true">
         <name>android.hardware.security.secureclock</name>
         <version>1</version>
@@ -629,7 +638,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.vibrator</name>
-        <version>1-2</version>
+        <version>1-3</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
@@ -637,13 +646,22 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.vibrator</name>
-        <version>1-2</version>
+        <version>1-3</version>
         <interface>
             <name>IVibratorManager</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="aidl">
+      <name>android.hardware.virtualization.capabilities</name>
+        <version>1</version>
+        <interface>
+            <name>IVmCapabilitiesService</name>
+            <instance>default</instance>
+            <instance>noop</instance>
+        </interface>
+    </hal>
+    <hal format="aidl">
         <name>android.hardware.weaver</name>
         <version>2</version>
         <interface>
@@ -669,7 +687,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.wifi.hostapd</name>
-        <version>1-2</version>
+        <version>2-3</version>
         <interface>
             <name>IHostapd</name>
             <instance>default</instance>
@@ -677,7 +695,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.wifi.supplicant</name>
-        <version>2-3</version>
+        <version>3-4</version>
         <interface>
             <name>ISupplicant</name>
             <instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.mk b/compatibility_matrices/compatibility_matrix.mk
deleted file mode 100644
index d22e510..0000000
--- a/compatibility_matrices/compatibility_matrix.mk
+++ /dev/null
@@ -1,128 +0,0 @@
-#
-# Copyright (C) 2018 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.
-#
-
-##### Input Variables:
-# LOCAL_MODULE: required. Module name for the build system.
-# LOCAL_MODULE_CLASS: optional. Default is ETC.
-# LOCAL_MODULE_PATH / LOCAL_MODULE_RELATIVE_PATH: required. (Relative) path of output file.
-#       If not defined, LOCAL_MODULE_RELATIVE_PATH will be "vintf".
-# LOCAL_MODULE_STEM: optional. Name of output file. Default is $(LOCAL_MODULE).
-# LOCAL_SRC_FILES: required. Local source files provided to assemble_vintf
-#       (command line argument -i).
-# LOCAL_GENERATED_SOURCES: optional. Global source files provided to assemble_vintf
-#       (command line argument -i).
-#
-# LOCAL_ADD_VBMETA_VERSION: Use AVBTOOL to add avb version to the output matrix
-#       (corresponds to <avb><vbmeta-version> tag)
-# LOCAL_ASSEMBLE_VINTF_ENV_VARS: Add a list of environment variable names from global variables in
-#       the build system that is lazily evaluated (e.g. PRODUCT_ENFORCE_VINTF_MANIFEST).
-# LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE: Add a list of environment variables that is local to
-#       assemble_vintf invocation. Format is "VINTF_ENFORCE_NO_UNUSED_HALS=true".
-# LOCAL_ASSEMBLE_VINTF_FLAGS: Add additional command line arguments to assemble_vintf invocation.
-# LOCAL_KERNEL_CONFIG_DATA_PATHS: Paths to search for kernel config requirements. Format for each is
-#       <kernel version x.y.z>:<path that contains android-base*.config>.
-# LOCAL_GEN_FILE_DEPENDENCIES: A list of additional dependencies for the generated file.
-
-ifndef LOCAL_MODULE
-$(error LOCAL_MODULE must be defined.)
-endif
-
-ifndef LOCAL_MODULE_STEM
-LOCAL_MODULE_STEM := $(LOCAL_MODULE)
-endif
-
-ifndef LOCAL_MODULE_CLASS
-LOCAL_MODULE_CLASS := ETC
-endif
-
-ifndef LOCAL_MODULE_PATH
-ifndef LOCAL_MODULE_RELATIVE_PATH
-$(error Either LOCAL_MODULE_PATH or LOCAL_MODULE_RELATIVE_PATH must be defined.)
-endif
-endif
-
-GEN := $(local-generated-sources-dir)/$(LOCAL_MODULE_STEM)
-
-$(GEN): PRIVATE_ENV_VARS := $(LOCAL_ASSEMBLE_VINTF_ENV_VARS)
-$(GEN): PRIVATE_FLAGS := $(LOCAL_ASSEMBLE_VINTF_FLAGS)
-
-$(GEN): $(LOCAL_GEN_FILE_DEPENDENCIES)
-
-ifeq (true,$(strip $(LOCAL_ADD_VBMETA_VERSION)))
-ifeq (true,$(BOARD_AVB_ENABLE))
-$(GEN): $(AVBTOOL)
-# INTERNAL_AVB_SYSTEM_SIGNING_ARGS consists of BOARD_AVB_SYSTEM_KEY_PATH and
-# BOARD_AVB_SYSTEM_ALGORITHM. We should add the dependency of key path, which
-# is a file, here.
-$(GEN): $(BOARD_AVB_SYSTEM_KEY_PATH)
-# Use deferred assignment (=) instead of immediate assignment (:=).
-# Otherwise, cannot get INTERNAL_AVB_SYSTEM_SIGNING_ARGS.
-$(GEN): FRAMEWORK_VBMETA_VERSION = $$("$(AVBTOOL)" add_hashtree_footer \
-                           --print_required_libavb_version \
-                           $(INTERNAL_AVB_SYSTEM_SIGNING_ARGS) \
-                           $(BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS))
-else
-$(GEN): FRAMEWORK_VBMETA_VERSION := 0.0
-endif # BOARD_AVB_ENABLE
-$(GEN): PRIVATE_ENV_VARS += FRAMEWORK_VBMETA_VERSION
-endif # LOCAL_ADD_VBMETA_VERSION
-
-ifeq (true,$(strip $(LOCAL_ADD_VBMETA_VERSION_OVERRIDE)))
-ifneq ($(BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE),)
-$(GEN): FRAMEWORK_VBMETA_VERSION_OVERRIDE := $(BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE)
-$(GEN): PRIVATE_ENV_VARS += FRAMEWORK_VBMETA_VERSION_OVERRIDE
-endif
-endif
-
-ifneq (,$(strip $(LOCAL_KERNEL_CONFIG_DATA_PATHS)))
-$(GEN): PRIVATE_KERNEL_CONFIG_DATA_PATHS := $(LOCAL_KERNEL_CONFIG_DATA_PATHS)
-$(GEN): $(foreach pair,$(LOCAL_KERNEL_CONFIG_DATA_PATHS),\
-    $(wildcard $(call word-colon,2,$(pair))/android-base*.config))
-$(GEN): PRIVATE_FLAGS += $(foreach pair,$(PRIVATE_KERNEL_CONFIG_DATA_PATHS),\
-	--kernel=$(call word-colon,1,$(pair)):$(call normalize-path-list,\
-		$(wildcard $(call word-colon,2,$(pair))/android-base*.config)))
-endif
-
-my_matrix_src_files := \
-	$(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES)) \
-	$(LOCAL_GENERATED_SOURCES)
-
-$(GEN): PRIVATE_ADDITIONAL_ENV_VARS := $(LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE)
-
-ifneq (,$(strip $(LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE)))
-$(GEN): PRIVATE_COMMAND_TAIL := || (echo $(strip $(LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE)) && false)
-endif
-
-$(GEN): PRIVATE_SRC_FILES := $(my_matrix_src_files)
-$(GEN): $(my_matrix_src_files) $(HOST_OUT_EXECUTABLES)/assemble_vintf
-	$(foreach varname,$(PRIVATE_ENV_VARS),\
-		$(if $(findstring $(varname),$(PRIVATE_ADDITIONAL_ENV_VARS)),\
-			$(error $(varname) should not be overridden by LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE.)))
-	$(foreach varname,$(PRIVATE_ENV_VARS),$(varname)="$($(varname))") \
-		$(PRIVATE_ADDITIONAL_ENV_VARS) \
-		$(HOST_OUT_EXECUTABLES)/assemble_vintf \
-		-i $(call normalize-path-list,$(PRIVATE_SRC_FILES)) \
-		-o $@ \
-		$(PRIVATE_FLAGS) $(PRIVATE_COMMAND_TAIL)
-
-LOCAL_PREBUILT_MODULE_FILE := $(GEN)
-LOCAL_SRC_FILES :=
-LOCAL_GENERATED_SOURCES :=
-
-include $(LOCAL_PATH)/clear_vars.mk
-my_matrix_src_files :=
-
-include $(BUILD_PREBUILT)
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index fca9e1c..1d5b2bd 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -149,6 +149,7 @@
             "android.hardware.radio@",
             "android.hardware.uwb.fira_android@",
             "android.hardware.wifi.common@",
+            "android.hardware.biometrics.fingerprint.virtualhal@",
 
             // Test packages are exempted.
             "android.hardware.tests.",
@@ -156,6 +157,8 @@
             // Fastboot HAL is only used by recovery. Recovery is owned by OEM. Framework
             // does not depend on this HAL, hence it is not declared in any manifests or matrices.
             "android.hardware.fastboot@",
+            "android.hardware.security.see.hwcrypto.types",
+            "android.hardware.security.see.storage",
     };
 
     static std::vector<std::string> excluded_exact{
@@ -165,8 +168,12 @@
             "android.hardware.audio.core.sounddose@1",
             "android.hardware.audio.core.sounddose@2",
             "android.hardware.audio.core.sounddose@3",
+            // This is only used by a trusty VM
+            "android.hardware.security.see.authmgr@1",
+            "android.hardware.security.see.hdcp@1",
 
             // Deprecated HALs.
+            "android.hardware.audio.sounddose@3",
             "android.hardware.bluetooth.audio@1",
     };
 
diff --git a/configstore/1.0/vts/functional/Android.bp b/configstore/1.0/vts/functional/Android.bp
index 27c66fd..388c565 100644
--- a/configstore/1.0/vts/functional/Android.bp
+++ b/configstore/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/configstore/1.1/default/Android.bp b/configstore/1.1/default/Android.bp
new file mode 100644
index 0000000..34470ad
--- /dev/null
+++ b/configstore/1.1/default/Android.bp
@@ -0,0 +1,142 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//###############################################################################
+package {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: [
+        "hardware_interfaces_license",
+    ],
+}
+
+soong_config_module_type {
+    name: "surfaceflinger_cc_defaults_type",
+    module_type: "cc_defaults",
+    config_namespace: "surfaceflinger",
+    value_variables: [
+        "vsync_event_phase_offset_ns",
+        "sf_vsync_event_phase_offset_ns",
+        "present_time_offset_from_vsync_ns",
+        "max_virtual_displat_dimension",
+        "num_framebuffer_surface_buffers",
+        "sf_primary_display_orientation",
+    ],
+    bool_variables: [
+        "use_context_priority",
+        "has_wide_color_display",
+        "has_hdr_display",
+        "force_hwc_copy_for_virtual_displays",
+        "running_without_sync_framework",
+        "use_vr_flinger",
+        "sf_start_graphics_allocator_service",
+    ],
+    properties: [
+        "cflags",
+    ],
+}
+
+surfaceflinger_cc_defaults_type {
+    name: "surfaceflinger_cc_defaults",
+    srcs: [
+        "SurfaceFlingerConfigs.cpp",
+    ],
+    soong_config_variables: {
+        vsync_event_phase_offset_ns: {
+            cflags: ["-DVSYNC_EVENT_PHASE_OFFSET_NS=%s"],
+        },
+        sf_vsync_event_phase_offset_ns: {
+            cflags: ["-DSF_VSYNC_EVENT_PHASE_OFFSET_NS=%s"],
+        },
+        present_time_offset_from_vsync_ns: {
+            cflags: ["-DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=%s"],
+        },
+        max_virtual_displat_dimension: {
+            cflags: ["-DMAX_VIRTUAL_DISPLAY_DIMENSION=%s"],
+        },
+        num_framebuffer_surface_buffers: {
+            cflags: ["-DNUM_FRAMEBUFFER_SURFACE_BUFFERS=%s"],
+        },
+        sf_primary_display_orientation: {
+            cflags: ["-DPRIMARY_DISPLAY_ORIENTATION=%s"],
+        },
+        use_context_priority: {
+            cflags: ["-DUSE_CONTEXT_PRIORITY=1"],
+        },
+        has_wide_color_display: {
+            cflags: ["-DHAS_WIDE_COLOR_DISPLAY"],
+        },
+        has_hdr_display: {
+            cflags: ["-DHAS_HDR_DISPLAY"],
+        },
+        force_hwc_copy_for_virtual_displays: {
+            cflags: ["-DFORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS"],
+        },
+        running_without_sync_framework: {
+            cflags: ["-DRUNNING_WITHOUT_SYNC_FRAMEWORK"],
+        },
+        use_vr_flinger: {
+            cflags: ["-DUSE_VR_FLINGER"],
+        },
+        sf_start_graphics_allocator_service: {
+            cflags: ["-DSTART_GRAPHICS_ALLOCATOR_SERVICE"],
+        },
+    },
+}
+
+cc_binary {
+    name: "android.hardware.configstore@1.1-service",
+    srcs: ["service.cpp"],
+    vendor: true,
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.configstore@1.1-service.rc"],
+    shared_libs: [
+        "libhidlbase",
+        "libbase",
+        "libhwminijail",
+        "liblog",
+        "libutils",
+        "android.hardware.configstore@1.0",
+        "android.hardware.configstore@1.1",
+    ],
+    defaults: [
+        "surfaceflinger_cc_defaults",
+    ],
+    required: select((arch(), soong_config_variable("ANDROID", "GCOV_COVERAGE")), {
+        ("arm64", false): ["configstore@1.1.policy"],
+        (default, default): [],
+    }),
+}
+
+// Only build for arm64
+prebuilt_etc {
+    name: "configstore@1.1.policy",
+    relative_install_path: "seccomp_policy",
+    proprietary: true,
+    enabled: false,
+    arch: {
+        arm64: {
+            src: "seccomp_policy/configstore@1.1-arm64.policy",
+            enabled: true,
+        },
+    },
+}
+
+// disable configstore
+cc_binary {
+    name: "disable_configstore",
+    installable: false,
+    srcs: ["disable_configstore.cpp"],
+    overrides: ["android.hardware.configstore@1.1-service"],
+    vendor: true,
+}
diff --git a/configstore/1.1/default/Android.mk b/configstore/1.1/default/Android.mk
deleted file mode 100644
index 9a6f0fc..0000000
--- a/configstore/1.1/default/Android.mk
+++ /dev/null
@@ -1,57 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-################################################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.configstore@1.1-service
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-# seccomp is not required for coverage build.
-ifneq ($(NATIVE_COVERAGE),true)
-LOCAL_REQUIRED_MODULES_arm64 := configstore@1.1.policy
-endif
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_INIT_RC := android.hardware.configstore@1.1-service.rc
-LOCAL_SRC_FILES:= service.cpp
-
-include $(LOCAL_PATH)/surfaceflinger.mk
-
-LOCAL_SHARED_LIBRARIES := \
-    libhidlbase \
-    libbase \
-    libhwminijail \
-    liblog \
-    libutils \
-    android.hardware.configstore@1.0 \
-    android.hardware.configstore@1.1
-
-include $(BUILD_EXECUTABLE)
-
-# seccomp filter for configstore
-ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm64))
-include $(CLEAR_VARS)
-LOCAL_MODULE := configstore@1.1.policy
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/seccomp_policy
-LOCAL_SRC_FILES := seccomp_policy/configstore@1.1-$(TARGET_ARCH).policy
-include $(BUILD_PREBUILT)
-endif
-
-# disable configstore
-include $(CLEAR_VARS)
-LOCAL_MODULE := disable_configstore
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_SRC_FILES:= disable_configstore.cpp
-LOCAL_OVERRIDES_MODULES := android.hardware.configstore@1.1-service
-LOCAL_VENDOR_MODULE := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_EXECUTABLE)
diff --git a/configstore/1.1/default/surfaceflinger.mk b/configstore/1.1/default/surfaceflinger.mk
index 35922eb..462fe85 100644
--- a/configstore/1.1/default/surfaceflinger.mk
+++ b/configstore/1.1/default/surfaceflinger.mk
@@ -2,55 +2,69 @@
 LOCAL_SRC_FILES += SurfaceFlingerConfigs.cpp
 
 ifneq ($(VSYNC_EVENT_PHASE_OFFSET_NS),)
+    $(call soong_config_set,surfaceflinger,vsync_event_phase_offset_ns,$(VSYNC_EVENT_PHASE_OFFSET_NS))
     LOCAL_CFLAGS += -DVSYNC_EVENT_PHASE_OFFSET_NS=$(VSYNC_EVENT_PHASE_OFFSET_NS)
 endif
 
 ifneq ($(SF_VSYNC_EVENT_PHASE_OFFSET_NS),)
+    $(call soong_config_set,surfaceflinger,sf_vsync_event_phase_offset_ns,$(SF_VSYNC_EVENT_PHASE_OFFSET_NS))
     LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=$(SF_VSYNC_EVENT_PHASE_OFFSET_NS)
 endif
 
 ifeq ($(TARGET_USE_CONTEXT_PRIORITY),true)
+    $(call soong_config_set_bool,surfaceflinger,use_context_priority,true)
     LOCAL_CFLAGS += -DUSE_CONTEXT_PRIORITY=1
 endif
 
 ifeq ($(TARGET_HAS_WIDE_COLOR_DISPLAY),true)
+    $(call soong_config_set_bool,surfaceflinger,has_wide_color_display,true)
     LOCAL_CFLAGS += -DHAS_WIDE_COLOR_DISPLAY
 endif
 
 ifeq ($(TARGET_HAS_HDR_DISPLAY),true)
+    $(call soong_config_set_bool,surfaceflinger,has_hdr_display,true)
     LOCAL_CFLAGS += -DHAS_HDR_DISPLAY
 endif
 
 ifneq ($(PRESENT_TIME_OFFSET_FROM_VSYNC_NS),)
+    $(call soong_config_set,surfaceflinger,present_time_offset_from_vsync_ns,$(PRESENT_TIME_OFFSET_FROM_VSYNC_NS))
     LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=$(PRESENT_TIME_OFFSET_FROM_VSYNC_NS)
 else
+    $(call soong_config_set,surfaceflinger,present_time_offset_from_vsync_ns,0)
     LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=0
 endif
 
 ifeq ($(TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS),true)
+    $(call soong_config_set_bool,surfaceflinger,force_hwc_copy_for_virtual_displays,true)
     LOCAL_CFLAGS += -DFORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS
 endif
 
 ifneq ($(MAX_VIRTUAL_DISPLAY_DIMENSION),)
+    $(call soong_config_set,surfaceflinger,max_virtual_displat_dimension,$(MAX_VIRTUAL_DISPLAY_DIMENSION))
     LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=$(MAX_VIRTUAL_DISPLAY_DIMENSION)
 endif
 
 ifeq ($(TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK),true)
+    $(call soong_config_set_bool,surfaceflinger,running_without_sync_framework,true)
     LOCAL_CFLAGS += -DRUNNING_WITHOUT_SYNC_FRAMEWORK
 endif
 
 ifneq ($(USE_VR_FLINGER),)
+    $(call soong_config_set_bool,surfaceflinger,use_vr_flinger,true)
     LOCAL_CFLAGS += -DUSE_VR_FLINGER
 endif
 
 ifneq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),)
+    $(call soong_config_set,surfaceflinger,num_framebuffer_surface_buffers,$(NUM_FRAMEBUFFER_SURFACE_BUFFERS))
     LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
 endif
 
 ifneq ($(SF_START_GRAPHICS_ALLOCATOR_SERVICE),)
+    $(call soong_config_set_bool,surfaceflinger,sf_start_graphics_allocator_service,true)
     LOCAL_CFLAGS += -DSTART_GRAPHICS_ALLOCATOR_SERVICE
 endif
 
 ifneq ($(SF_PRIMARY_DISPLAY_ORIENTATION),)
+    $(call soong_config_set,surfaceflinger,sf_primary_display_orientation,$(SF_PRIMARY_DISPLAY_ORIENTATION))
     LOCAL_CFLAGS += -DPRIMARY_DISPLAY_ORIENTATION=$(SF_PRIMARY_DISPLAY_ORIENTATION)
 endif
diff --git a/confirmationui/1.0/vts/functional/Android.bp b/confirmationui/1.0/vts/functional/Android.bp
index 6c6488b..2fbd851 100644
--- a/confirmationui/1.0/vts/functional/Android.bp
+++ b/confirmationui/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_platform_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/confirmationui/aidl/Android.bp b/confirmationui/aidl/Android.bp
index 51bde0a..1f17866 100644
--- a/confirmationui/aidl/Android.bp
+++ b/confirmationui/aidl/Android.bp
@@ -19,8 +19,8 @@
 aidl_interface {
     name: "android.hardware.confirmationui",
     vendor_available: true,
-    imports: [
-        "android.hardware.security.keymint-V3",
+    defaults: [
+        "android.hardware.security.keymint-latest-defaults",
     ],
     srcs: ["android/hardware/confirmationui/*.aidl"],
     stability: "vintf",
@@ -38,7 +38,7 @@
     versions_with_info: [
         {
             version: "1",
-            imports: ["android.hardware.security.keymint-V3"],
+            imports: ["android.hardware.security.keymint-V4"],
         },
     ],
     frozen: true,
diff --git a/confirmationui/aidl/vts/functional/Android.bp b/confirmationui/aidl/vts/functional/Android.bp
index ac2d53a..2403185 100644
--- a/confirmationui/aidl/vts/functional/Android.bp
+++ b/confirmationui/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_platform_security",
     // See: http://go/android-license-faq
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
diff --git a/contexthub/1.0/vts/functional/Android.bp b/contexthub/1.0/vts/functional/Android.bp
index 5949f8d..3bc3597 100644
--- a/contexthub/1.0/vts/functional/Android.bp
+++ b/contexthub/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_context_hub",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/contexthub/1.1/vts/functional/Android.bp b/contexthub/1.1/vts/functional/Android.bp
index b2961c4..5e0779d 100644
--- a/contexthub/1.1/vts/functional/Android.bp
+++ b/contexthub/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_context_hub",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/contexthub/1.2/vts/functional/Android.bp b/contexthub/1.2/vts/functional/Android.bp
index c923f42..cdf348f 100644
--- a/contexthub/1.2/vts/functional/Android.bp
+++ b/contexthub/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_context_hub",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/contexthub/OWNERS b/contexthub/OWNERS
index f35961a..ccd385b 100644
--- a/contexthub/OWNERS
+++ b/contexthub/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 156070
 bduddie@google.com
+arthuri@google.com
diff --git a/contexthub/aidl/Android.bp b/contexthub/aidl/Android.bp
index 202813c..b56537a 100644
--- a/contexthub/aidl/Android.bp
+++ b/contexthub/aidl/Android.bp
@@ -33,7 +33,12 @@
             sdk_version: "module_current",
         },
         ndk: {
-            apps_enabled: false,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.bt",
+            ],
+            min_sdk_version: "33",
+            apps_enabled: true,
         },
         rust: {
             enabled: true,
@@ -52,8 +57,6 @@
             version: "3",
             imports: [],
         },
-
     ],
-    frozen: true,
-
+    frozen: false,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/EndpointId.aidl
similarity index 88%
rename from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
rename to contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/EndpointId.aidl
index 173ac17..a70065d 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/EndpointId.aidl
@@ -31,10 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.contexthub;
 @VintfStability
-parcelable EnrollmentProgressStep {
-  int durationMs;
-  android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes;
+parcelable EndpointId {
+  long id;
+  long hubId;
+  const long ENDPOINT_ID_INVALID = 0;
+  const long ENDPOINT_ID_RESERVED = (-1) /* -1 */;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/EndpointInfo.aidl
similarity index 78%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/EndpointInfo.aidl
index c1dc51c..43e5ec3 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/EndpointInfo.aidl
@@ -31,10 +31,22 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.contexthub;
 @VintfStability
-union AcquiredInfoAndVendorCode {
-  android.hardware.biometrics.fingerprint.AcquiredInfo acquiredInfo = android.hardware.biometrics.fingerprint.AcquiredInfo.UNKNOWN;
-  int vendorCode;
+parcelable EndpointInfo {
+  android.hardware.contexthub.EndpointId id;
+  android.hardware.contexthub.EndpointInfo.EndpointType type;
+  String name;
+  int version;
+  @nullable String tag;
+  String[] requiredPermissions;
+  android.hardware.contexthub.Service[] services;
+  @Backing(type="int") @VintfStability
+  enum EndpointType {
+    FRAMEWORK = 1,
+    APP = 2,
+    NATIVE = 3,
+    NANOAPP = 4,
+    GENERIC = 5,
+  }
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/HubInfo.aidl
similarity index 81%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/HubInfo.aidl
index c1dc51c..cac441a 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/HubInfo.aidl
@@ -31,10 +31,15 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.contexthub;
 @VintfStability
-union AcquiredInfoAndVendorCode {
-  android.hardware.biometrics.fingerprint.AcquiredInfo acquiredInfo = android.hardware.biometrics.fingerprint.AcquiredInfo.UNKNOWN;
-  int vendorCode;
+parcelable HubInfo {
+  long hubId;
+  android.hardware.contexthub.HubInfo.HubDetails hubDetails;
+  const long HUB_ID_INVALID = 0;
+  const long HUB_ID_RESERVED = (-1) /* -1 */;
+  union HubDetails {
+    android.hardware.contexthub.ContextHubInfo contextHubInfo;
+    android.hardware.contexthub.VendorHubInfo vendorHubInfo;
+  }
 }
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
index 7341e0e..93b8ff5 100644
--- a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
@@ -49,5 +49,16 @@
   void onNanSessionStateChanged(in android.hardware.contexthub.NanSessionStateUpdate update);
   void setTestMode(in boolean enable);
   void sendMessageDeliveryStatusToHub(in int contextHubId, in android.hardware.contexthub.MessageDeliveryStatus messageDeliveryStatus);
+  List<android.hardware.contexthub.HubInfo> getHubs();
+  List<android.hardware.contexthub.EndpointInfo> getEndpoints();
+  void registerEndpoint(in android.hardware.contexthub.EndpointInfo endpoint);
+  void unregisterEndpoint(in android.hardware.contexthub.EndpointInfo endpoint);
+  void registerEndpointCallback(in android.hardware.contexthub.IEndpointCallback callback);
+  int[] requestSessionIdRange(int size);
+  void openEndpointSession(int sessionId, in android.hardware.contexthub.EndpointId destination, in android.hardware.contexthub.EndpointId initiator, in @nullable String serviceDescriptor);
+  void sendMessageToEndpoint(int sessionId, in android.hardware.contexthub.Message msg);
+  void sendMessageDeliveryStatusToEndpoint(int sessionId, in android.hardware.contexthub.MessageDeliveryStatus msgStatus);
+  void closeEndpointSession(int sessionId, in android.hardware.contexthub.Reason reason);
+  void endpointSessionOpenComplete(int sessionId);
   const int EX_CONTEXT_HUB_UNSPECIFIED = (-1) /* -1 */;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IEndpointCallback.aidl
similarity index 66%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IEndpointCallback.aidl
index c1dc51c..c0bb744 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IEndpointCallback.aidl
@@ -31,10 +31,14 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.contexthub;
 @VintfStability
-union AcquiredInfoAndVendorCode {
-  android.hardware.biometrics.fingerprint.AcquiredInfo acquiredInfo = android.hardware.biometrics.fingerprint.AcquiredInfo.UNKNOWN;
-  int vendorCode;
+interface IEndpointCallback {
+  void onEndpointStarted(in android.hardware.contexthub.EndpointInfo[] endpointInfos);
+  void onEndpointStopped(in android.hardware.contexthub.EndpointId[] endpointIds, android.hardware.contexthub.Reason reason);
+  void onMessageReceived(int sessionId, in android.hardware.contexthub.Message msg);
+  void onMessageDeliveryStatusReceived(int sessionId, in android.hardware.contexthub.MessageDeliveryStatus msgStatus);
+  void onEndpointSessionOpenRequest(int sessionId, in android.hardware.contexthub.EndpointId destination, in android.hardware.contexthub.EndpointId initiator, in @nullable String serviceDescriptor);
+  void onCloseEndpointSession(int sessionId, in android.hardware.contexthub.Reason reason);
+  void onEndpointSessionOpenComplete(int sessionId);
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Message.aidl
similarity index 88%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
copy to contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Message.aidl
index 173ac17..ef117c3 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Message.aidl
@@ -31,10 +31,13 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.contexthub;
 @VintfStability
-parcelable EnrollmentProgressStep {
-  int durationMs;
-  android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes;
+parcelable Message {
+  int flags;
+  int sequenceNumber;
+  String[] permissions;
+  int type;
+  byte[] content;
+  const int FLAG_REQUIRES_DELIVERY_STATUS = 1;
 }
diff --git a/drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevel.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Reason.aidl
similarity index 82%
copy from drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevel.aidl
copy to contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Reason.aidl
index 5704fb0..a315438 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevel.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Reason.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -31,15 +31,16 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.drm;
-@Backing(type="int") @VintfStability
-enum HdcpLevel {
-  HDCP_UNKNOWN = 0,
-  HDCP_NONE = 1,
-  HDCP_V1 = 2,
-  HDCP_V2 = 3,
-  HDCP_V2_1 = 4,
-  HDCP_V2_2 = 5,
-  HDCP_NO_OUTPUT = 6,
-  HDCP_V2_3 = 7,
+package android.hardware.contexthub;
+@Backing(type="byte") @VintfStability
+enum Reason {
+  UNSPECIFIED = 0,
+  OUT_OF_MEMORY,
+  TIMEOUT,
+  OPEN_ENDPOINT_SESSION_REQUEST_REJECTED,
+  CLOSE_ENDPOINT_SESSION_REQUESTED,
+  ENDPOINT_INVALID,
+  ENDPOINT_GONE,
+  ENDPOINT_CRASHED,
+  HUB_RESET,
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Service.aidl
similarity index 83%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Service.aidl
index c1dc51c..e3d94c8 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/Service.aidl
@@ -31,10 +31,18 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.contexthub;
 @VintfStability
-union AcquiredInfoAndVendorCode {
-  android.hardware.biometrics.fingerprint.AcquiredInfo acquiredInfo = android.hardware.biometrics.fingerprint.AcquiredInfo.UNKNOWN;
-  int vendorCode;
+parcelable Service {
+  android.hardware.contexthub.Service.RpcFormat format;
+  String serviceDescriptor;
+  int majorVersion;
+  int minorVersion;
+  ParcelableHolder extendedInfo;
+  @Backing(type="int") @VintfStability
+  enum RpcFormat {
+    CUSTOM = 0,
+    AIDL = 1,
+    PW_RPC_PROTOBUF = 2,
+  }
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/VendorHubInfo.aidl
similarity index 88%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/VendorHubInfo.aidl
index ca8b3eb..db64ec7 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/VendorHubInfo.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -31,8 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.contexthub;
+@VintfStability
+parcelable VendorHubInfo {
+  String name;
+  int version;
+  ParcelableHolder extendedInfo;
 }
diff --git a/contexthub/aidl/android/hardware/contexthub/EndpointId.aidl b/contexthub/aidl/android/hardware/contexthub/EndpointId.aidl
new file mode 100644
index 0000000..2075e73
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/EndpointId.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+/* This structure is a unique identifier for an endpoint */
+@VintfStability
+parcelable EndpointId {
+    /**
+     * Invalid endpoint ID.
+     */
+    const long ENDPOINT_ID_INVALID = 0;
+
+    /**
+     * Reserved endpoint ID.
+     */
+    const long ENDPOINT_ID_RESERVED = -1;
+
+    /**
+     * Nanoapp ID or randomly generated ID (depending on type). This value uniquely identifies the
+     * endpoint within a single hub.
+     *
+     * ENDPOINT_ID_INVALID(0) is an invalid id and should never be used.
+     * ENDPOINT_ID_RESERVED(-1) is reserved for future use.
+     * For static/compile-time-generated IDs, topmost bit should be 0.
+     * For dynamic/runtime-generated IDs, topmost bit should be 1.
+     */
+    long id;
+
+    /**
+     * Hub ID of the hub hosting this endpoint. A pair of (hubId, id) uniquely identifies the
+     * endpoint globally.
+     */
+    long hubId;
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/EndpointInfo.aidl b/contexthub/aidl/android/hardware/contexthub/EndpointInfo.aidl
new file mode 100644
index 0000000..53a41fc
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/EndpointInfo.aidl
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+import android.hardware.contexthub.EndpointId;
+import android.hardware.contexthub.Service;
+
+/* This structure is a unified superset of NanoAppInfo and HostEndpointInfo. */
+@VintfStability
+parcelable EndpointInfo {
+    /** Unique identifier of this endpoint. */
+    EndpointId id;
+
+    /** Type of this endpoint. */
+    EndpointType type;
+
+    /**
+     * Name of this endpoint. Endpoint may use this field to identify the initiator of the session
+     * request.
+     *
+     * Depending on type of the endpoint, the following values are used:
+     *  - Framework: package name of the process registering this endpoint
+     *  - App: package name of the process registering this endpoint
+     *  - Native: name of the process registering this endpoint, supplied by client for debugging
+     *            purpose.
+     *  - Nanoapp: name of the nanoapp, for debugging purpose
+     *  - Generic: name of the generic endpoint, for debugging purpose
+     */
+    String name;
+
+    /**
+     * Monotonically increasing version number. The two sides of an endpoint session can use this
+     * version number to identify the other side and determine compatibility with each other.
+     * The interpretation of the version number is specific to the implementation of an endpoint.
+     * The version number should not be used to compare endpoints implementation freshness for
+     * different endpoint types.
+     *
+     * Depending on type of the endpoint, the following values are used:
+     *  - Framework: android.os.Build.VERSION.SDK_INT_FULL (populated by ContextHubService)
+     *  - App: versionCode (populated by ContextHubService)
+     *  - Native: unspecified format (supplied by endpoint code)
+     *  - Nanoapp: nanoapp version, typically following 0xMMmmpppp scheme where
+     *             MM = major version, mm = minor version, pppp = patch version
+     *  - Generic: unspecified format (supplied by endpoint code), following nanoapp versioning
+     *             scheme is recommended
+     */
+    int version;
+
+    /**
+     * Tag for this particular endpoint. Optional string that further identifies the submodule
+     * that created this endpoint.
+     */
+    @nullable String tag;
+
+    /**
+     * Represents the minimally required permissions in order to message this endpoint. Further
+     * permissions may be required on a message-by-message basis.
+     */
+    String[] requiredPermissions;
+
+    /**
+     * List of services provided by this endpoint. Service list should be fixed for the
+     * lifetime of an endpoint.
+     */
+    Service[] services;
+
+    @VintfStability
+    @Backing(type="int")
+    enum EndpointType {
+        /**
+         * This endpoint is from the Android framework
+         */
+        FRAMEWORK = 1,
+
+        /** This endpoint is an Android app. */
+        APP = 2,
+
+        /** This endpoint is from an Android native program. */
+        NATIVE = 3,
+
+        /** This endpoint is from a nanoapp. */
+        NANOAPP = 4,
+
+        /** This endpoint is a generic endpoint (not from a nanoapp). */
+        GENERIC = 5,
+    }
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/HubInfo.aidl b/contexthub/aidl/android/hardware/contexthub/HubInfo.aidl
new file mode 100644
index 0000000..3d0a76e
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/HubInfo.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+import android.hardware.contexthub.ContextHubInfo;
+import android.hardware.contexthub.VendorHubInfo;
+
+@VintfStability
+parcelable HubInfo {
+    /**
+     * Invalid hub ID.
+     */
+    const long HUB_ID_INVALID = 0;
+
+    /**
+     * Reserved hub ID.
+     */
+    const long HUB_ID_RESERVED = -1;
+
+    /**
+     * Hub ID (depending on type). This is a globally unique identifier.
+     *
+     * HUB_ID_INVALID(0) is an invalid id and should never be used.
+     * HUB_ID_RESERVED(-1) is reserved for future use.
+     */
+    long hubId;
+
+    /**
+     * A hub can be either a ContextHub or a VendorHub.
+     */
+    union HubDetails {
+        ContextHubInfo contextHubInfo;
+        VendorHubInfo vendorHubInfo;
+    }
+
+    /**
+     * Detail information about the hub.
+     */
+    HubDetails hubDetails;
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
index b146ff8..24192a1 100644
--- a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
@@ -18,12 +18,19 @@
 
 import android.hardware.contexthub.ContextHubInfo;
 import android.hardware.contexthub.ContextHubMessage;
+import android.hardware.contexthub.EndpointId;
+import android.hardware.contexthub.EndpointInfo;
 import android.hardware.contexthub.HostEndpointInfo;
+import android.hardware.contexthub.HubInfo;
 import android.hardware.contexthub.IContextHubCallback;
+import android.hardware.contexthub.IEndpointCallback;
+import android.hardware.contexthub.Message;
 import android.hardware.contexthub.MessageDeliveryStatus;
 import android.hardware.contexthub.NanSessionStateUpdate;
 import android.hardware.contexthub.NanoappBinary;
 import android.hardware.contexthub.NanoappInfo;
+import android.hardware.contexthub.Reason;
+import android.hardware.contexthub.Service;
 import android.hardware.contexthub.Setting;
 
 @VintfStability
@@ -221,7 +228,7 @@
     void onNanSessionStateChanged(in NanSessionStateUpdate update);
 
     /**
-     * Puts the context hub in and out of test mode. Test mode is a clean state
+     * Puts the Context Hub in and out of test mode. Test mode is a clean state
      * where tests can be executed in the same environment. If enable is true,
      * this will enable test mode by unloading all nanoapps. If enable is false,
      * this will disable test mode and reverse the actions of enabling test mode
@@ -231,7 +238,7 @@
      * @TestApi or development tools. This should not be used in a production
      * environment.
      *
-     * @param enable If true, put the context hub in test mode. If false, disable
+     * @param enable If true, put the Context Hub in test mode. If false, disable
      *               test mode.
      */
     void setTestMode(in boolean enable);
@@ -256,4 +263,136 @@
      * value EX_SERVICE_SPECIFIC.
      */
     const int EX_CONTEXT_HUB_UNSPECIFIED = -1;
+
+    /** Lists all the hubs, including the Context Hub and generic hubs. */
+    List<HubInfo> getHubs();
+
+    /** Lists all the endpoints, including the Context Hub nanoapps and generic endpoints. */
+    List<EndpointInfo> getEndpoints();
+
+    /**
+     * Publishes an endpoint from the calling side (e.g. Android). Endpoints must be registered
+     * prior to starting a session.
+     */
+    void registerEndpoint(in EndpointInfo endpoint);
+
+    /**
+     * Teardown an endpoint from the calling side (e.g. Android). This endpoint must have already
+     * been published via registerEndpoint().
+     */
+    void unregisterEndpoint(in EndpointInfo endpoint);
+
+    /**
+     * Attaches a callback interface to receive events targeted at endpoints registered by the
+     * caller.
+     */
+    void registerEndpointCallback(in IEndpointCallback callback);
+
+    /**
+     * Request a range of session IDs for the caller to use when initiating sessions. This may be
+     * called more than once, but typical usage is to request a large enough range to accommodate
+     * the maximum expected number of concurrent sessions, but not overly large as to limit other
+     * clients.
+     *
+     * @param size The number of sessionId reserved for host-initiated sessions. This number should
+     *         be less than or equal to 1024.
+     *
+     * @return An array with two elements representing the smallest and largest possible session id
+     *         available for host.
+     *
+     * @throws EX_ILLEGAL_ARGUMENT if the size is invalid.
+     * @throws EX_SERVICE_SPECIFIC if the id range requested cannot be allocated.
+     */
+    int[] requestSessionIdRange(int size);
+
+    /**
+     * Request to open a session for communication between an endpoint previously registered by the
+     * caller and a target endpoint found in getEndpoints(), optionally scoped to a service
+     * published by the target endpoint.
+     *
+     * Upon returning from this function, the session is in pending state, and the final result will
+     * be given by an asynchronous call to onEndpointSessionOpenComplete() on success, or
+     * onCloseEndpointSession() on failure.
+     *
+     * @param sessionId Caller-allocated session identifier, which must be unique across all active
+     *         sessions, and must fall in a range allocated via requestSessionIdRange().
+     * @param destination The EndpointId representing the destination side of the session.
+     * @param initiator The EndpointId representing the initiating side of the session, which
+     *         must've already been published through registerEndpoint().
+     * @param serviceDescriptor Descriptor for the service specification for scoping this session
+     *         (nullable). Null indicates a fully custom marshalling scheme. The value should match
+     *         a published descriptor for both destination and initiator.
+     *
+     * @return An integer identifying the session, the integer can be used to present
+     *         the tuple of (destination, initiator, serviceDescriptor).
+     *
+     * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
+     *         arguments is invalid.
+     * @throws EX_SERVICE_SPECIFIC on other errors
+     *         - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
+     */
+    void openEndpointSession(int sessionId, in EndpointId destination, in EndpointId initiator,
+            in @nullable String serviceDescriptor);
+
+    /**
+     * Send a message from one endpoint to another on the (currently open) session.
+     *
+     * @param sessionId The integer representing the communication session, previously set in
+     *         openEndpointSession() or onEndpointSessionOpenRequest().
+     * @param msg The Message object representing a message to endpoint from the endpoint on host.
+     *
+     * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
+     *         arguments is invalid.
+     * @throws EX_SERVICE_SPECIFIC on other errors
+     *         - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
+     */
+    void sendMessageToEndpoint(int sessionId, in Message msg);
+
+    /**
+     * Sends a message delivery status to the endpoint in response to receiving a Message with flag
+     * FLAG_REQUIRES_DELIVERY_STATUS. Each message with the flag should have a MessageDeliveryStatus
+     * response. This method sends the message delivery status back to the remote endpoint for a
+     * session.
+     *
+     * @param sessionId The integer representing the communication session, previously set in
+     *         openEndpointSession() or onEndpointSessionOpenRequest().
+     * @param msgStatus The MessageDeliveryStatus object representing the delivery status for a
+     *         specific message (identified by the sequenceNumber) within the session.
+     *
+     * @throws EX_UNSUPPORTED_OPERATION if ContextHubInfo.supportsReliableMessages is false for
+     *          the hub involved in this session.
+     */
+    void sendMessageDeliveryStatusToEndpoint(int sessionId, in MessageDeliveryStatus msgStatus);
+
+    /**
+     * Closes a session previously opened by openEndpointSession() or requested via
+     * onEndpointSessionOpenRequest(). Processing of session closure must be ordered/synchronized
+     * with message delivery, such that if this session was open, any messages previously passed to
+     * sendMessageToEndpoint() that are still in-flight must still be delivered before the session
+     * is closed. Any in-flight messages to the endpoint that requested to close the session will
+     * not be delivered.
+     *
+     * @param sessionId The integer representing the communication session, previously set in
+     *         openEndpointSession() or onEndpointSessionOpenRequest().
+     * @param reason The reason for this close endpoint session request.
+     *
+     * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
+     *         arguments is invalid.
+     * @throws EX_SERVICE_SPECIFIC on other errors
+     *         - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
+     */
+    void closeEndpointSession(int sessionId, in Reason reason);
+
+    /**
+     * Notifies the HAL that the session requested by onEndpointSessionOpenRequest is ready to use.
+     *
+     * @param sessionId The integer representing the communication session, previously set in
+     *         onEndpointSessionOpenRequest(). This id is assigned by the HAL.
+     *
+     * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
+     *         arguments is invalid.
+     * @throws EX_SERVICE_SPECIFIC on other errors
+     *         - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
+     */
+    void endpointSessionOpenComplete(int sessionId);
 }
diff --git a/contexthub/aidl/android/hardware/contexthub/IEndpointCallback.aidl b/contexthub/aidl/android/hardware/contexthub/IEndpointCallback.aidl
new file mode 100644
index 0000000..972853b
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/IEndpointCallback.aidl
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+import android.hardware.contexthub.EndpointId;
+import android.hardware.contexthub.EndpointInfo;
+import android.hardware.contexthub.Message;
+import android.hardware.contexthub.MessageDeliveryStatus;
+import android.hardware.contexthub.Reason;
+import android.hardware.contexthub.Service;
+
+@VintfStability
+interface IEndpointCallback {
+    /**
+     * Lifecycle event notification for endpoint starting from remote side. There is no need to
+     * report already started endpoint prior to the registration of an EndpointLifecycleCallbacks
+     * object. The EndpointInfo reported here should be consistent with values from getEndpoints().
+     *
+     * Endpoints added by registerEndpoint should not be included. registerEndpoint() should not
+     * cause this call.
+     *
+     * @param endpointInfos An array of EndpointInfo representing endpoints that just started.
+     */
+    void onEndpointStarted(in EndpointInfo[] endpointInfos);
+
+    /**
+     * Lifecycle event notification for endpoint stopping from remote side. There is no need to
+     * report already stopped endpoint prior to the registration of an EndpointLifecycleCallbacks
+     * object. The EndpointId reported here should represent a previously started Endpoint.
+     *
+     * When a hub crashes or restart, events should be batched into be a single call (containing all
+     * the EndpointId that were impacted).
+     *
+     * Endpoints added by registerEndpoint should not be included. unregisterEndpoint() should not
+     * cause this call.
+     *
+     * @param endpointIds An array of EndpointId representing endpoints that just stopped.
+     * @param reason The reason for why the endpoints stopped.
+     */
+    void onEndpointStopped(in EndpointId[] endpointIds, Reason reason);
+
+    /**
+     * Invoked when an endpoint sends message to another endpoint (on host) on the (currently open)
+     * session.
+     *
+     * @param sessionId The integer representing the communication session, previously set in
+     *         openEndpointSession() or onEndpointSessionOpenRequest().
+     * @param msg The Message object representing a message from endpoint to an endpoint on host.
+     */
+    void onMessageReceived(int sessionId, in Message msg);
+
+    /**
+     * Invoked when an endpoint sends the response for a message that requires delivery status.
+     *
+     * The response is the message delivery status of a recently sent message within a session. See
+     * sendMessageDeliveryStatusToEndpoint() for more details.
+     *
+     * @param sessionId The integer representing the communication session, previously set in
+     *         openEndpointSession() or onEndpointSessionOpenRequest().
+     * @param msgStatus The MessageDeliveryStatus object representing the delivery status for a
+     *         specific message (identified by the sequenceNumber) within the session.
+     */
+    void onMessageDeliveryStatusReceived(int sessionId, in MessageDeliveryStatus msgStatus);
+
+    /**
+     * Invoked when session initiation is requested by a remote endpoint. The receiving host client
+     * must later call endpointSessionOpenComplete() to indicate successful connection and
+     * acceptance of the session, or closeEndpointSession() to indicate failure.
+     *
+     * @param sessionId Caller-allocated session identifier, which must be unique across all active
+     *         sessions, and must not fall in a range allocated via requestSessionIdRange().
+     * @param destination The EndpointId representing the destination side of the session, which
+     *         must've already been published through registerEndpoint().
+     * @param initiator The EndpointId representing the initiating side of the session.
+     * @param serviceDescriptor Descriptor for the service specification for scoping this session
+     *         (nullable). Null indicates a fully custom marshalling scheme. The value should match
+     *         a published descriptor for both endpoints.
+     *
+     * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid, or the combination of the
+     *         arguments is invalid.
+     */
+    void onEndpointSessionOpenRequest(int sessionId, in EndpointId destination,
+            in EndpointId initiator, in @nullable String serviceDescriptor);
+
+    /**
+     * Invoked when a session has either failed to open, or has been closed by the remote side.
+     * Upon receiving this callback, the session is closed and further messages on it will not be
+     * delivered.
+     *
+     * @param sessionId The integer representing the communication session, previously set in
+     *         openEndpointSession() or onEndpointSessionOpenRequest().
+     * @param reason The reason for this close endpoint session notification.
+     */
+    void onCloseEndpointSession(int sessionId, in Reason reason);
+
+    /**
+     * Callback when a session is opened. This callback is the status callback for a previous
+     * openEndpointSession().
+     *
+     * @param sessionId The integer representing the communication session, previously set in
+     *         onEndpointSessionOpenRequest(). This id is assigned by the host.
+     */
+    void onEndpointSessionOpenComplete(int sessionId);
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/Message.aidl b/contexthub/aidl/android/hardware/contexthub/Message.aidl
new file mode 100644
index 0000000..fc81ab0
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/Message.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+@VintfStability
+parcelable Message {
+    /**
+     * Bitmask for flags field if this message requires a MessageDeliveryStatus for the
+     * sequenceNumber within 1 second.
+     */
+    const int FLAG_REQUIRES_DELIVERY_STATUS = 1;
+
+    /** Bitset of flags */
+    int flags;
+
+    /** Sequence number of this message */
+    int sequenceNumber;
+
+    /**
+     * Per message permission (used for app-op permission attribution).
+     */
+    String[] permissions;
+
+    /**
+     * The type of this message payload, following a scheme specific to the service or sending
+     * endpoint's communication protocol. This value can be used to distinguish the handling of
+     * content (e.g. for decoding). This could also be used as the complete content of the message
+     * if no additional payload is needed.
+     */
+    int type;
+
+    /**
+     * Content (payload) of the message. The format of the message is specific to the context of the
+     * message: the service or endpoints involved in the session, and the message type.
+     */
+    byte[] content;
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/MessageDeliveryStatus.aidl b/contexthub/aidl/android/hardware/contexthub/MessageDeliveryStatus.aidl
index ae425b3..4129981 100644
--- a/contexthub/aidl/android/hardware/contexthub/MessageDeliveryStatus.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/MessageDeliveryStatus.aidl
@@ -21,7 +21,8 @@
 @VintfStability
 parcelable MessageDeliveryStatus {
     /**
-     * The messageSequenceNumber of the ContextHubMessage to which this status applies.
+     * The messageSequenceNumber of the ContextHubMessage or Message to which this status is
+     * required.
      */
     int messageSequenceNumber;
 
diff --git a/contexthub/aidl/android/hardware/contexthub/Reason.aidl b/contexthub/aidl/android/hardware/contexthub/Reason.aidl
new file mode 100644
index 0000000..65d9f8a
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/Reason.aidl
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+@VintfStability
+@Backing(type="byte")
+enum Reason {
+    /**
+     * Unspecified reason.
+     */
+    UNSPECIFIED = 0,
+
+    /**
+     * Out of memory. There's not enough memory to perform this operation.
+     */
+    OUT_OF_MEMORY,
+
+    /**
+     * Timeout. This operation timed out.
+     */
+    TIMEOUT,
+
+    /**
+     * Endpoint rejected this openEndpointSession request.
+     */
+    OPEN_ENDPOINT_SESSION_REQUEST_REJECTED,
+
+    /**
+     * Endpoint requested closeEndpointSession.
+     */
+    CLOSE_ENDPOINT_SESSION_REQUESTED,
+
+    /**
+     * Invalid endpoint.
+     */
+    ENDPOINT_INVALID,
+
+    /**
+     * Endpoint is now stopped.
+     */
+    ENDPOINT_GONE,
+
+    /**
+     * Endpoint crashed.
+     */
+    ENDPOINT_CRASHED,
+
+    /**
+     * Hub was reset or is resetting.
+     */
+    HUB_RESET,
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/Service.aidl b/contexthub/aidl/android/hardware/contexthub/Service.aidl
new file mode 100644
index 0000000..fd748c3
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/Service.aidl
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+@VintfStability
+parcelable Service {
+    /**
+     * Type of the Service. This field defines the messaging format used for this service.
+     * The format refers to how the data would be marhsalled in messages between host endpoint (on
+     * Android) and endpoint on the Context Hub or generic hub.
+     */
+    RpcFormat format;
+
+    /**
+     * Uniquely identifies the interface (scoped to type). Conventions depend on interface type.
+     * Examples:
+     *   1. AOSP-defined AIDL: android.hardware.something.IFoo/default
+     *   2. Vendor-defined AIDL: com.example.something.IBar/default
+     *   3. Pigweed RPC with Protobuf: com.example.proto.ExampleService
+     */
+    String serviceDescriptor;
+
+    /** Breaking changes should be a major version bump. */
+    int majorVersion;
+    /** Monotonically increasing minor version. */
+    int minorVersion;
+
+    /** Hook for additional detail in vendor-specific type */
+    ParcelableHolder extendedInfo;
+
+    /**
+     * Supported messaging format for the service between the host and the hubs.
+     */
+    @VintfStability
+    @Backing(type="int")
+    enum RpcFormat {
+        /**
+         * Customized format for messaging. Fully customized and opaque messaging format.
+         */
+        CUSTOM = 0,
+        /**
+         * Binder-based messaging. The host endpoint is defining this service in Stable AIDL.
+         * Messages between endpoints that uses this service will be using the binder marhsalling
+         * format.
+         */
+        AIDL = 1,
+        /**
+         * Pigweed RPC messaging with Protobuf. This endpoint is a Pigweed RPC. Messages between
+         * endpoints will use Pigweed RPC marshalling format (protobuf).
+         */
+        PW_RPC_PROTOBUF = 2,
+    }
+}
diff --git a/contexthub/aidl/android/hardware/contexthub/VendorHubInfo.aidl b/contexthub/aidl/android/hardware/contexthub/VendorHubInfo.aidl
new file mode 100644
index 0000000..524c7e8
--- /dev/null
+++ b/contexthub/aidl/android/hardware/contexthub/VendorHubInfo.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.contexthub;
+
+/**
+ * A representation of a vendor-specific hub providing endpoints (with services). The hub does not
+ * run the Context Hub Runtime Environment, but exposes a similar messaging API.
+ */
+@VintfStability
+parcelable VendorHubInfo {
+    /** Descriptive name of the basic hub */
+    String name;
+
+    /** Version of the hub */
+    int version;
+
+    /** Hook for additional detail in vendor-specific type */
+    ParcelableHolder extendedInfo;
+}
diff --git a/contexthub/aidl/default/Android.bp b/contexthub/aidl/default/Android.bp
index 2960746..da173f9 100644
--- a/contexthub/aidl/default/Android.bp
+++ b/contexthub/aidl/default/Android.bp
@@ -30,7 +30,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.contexthub-V3-ndk",
+        "android.hardware.contexthub-V4-ndk",
     ],
     export_include_dirs: ["include"],
     srcs: [
@@ -51,7 +51,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.contexthub-V3-ndk",
+        "android.hardware.contexthub-V4-ndk",
     ],
     static_libs: [
         "libcontexthubexampleimpl",
diff --git a/contexthub/aidl/default/ContextHub.cpp b/contexthub/aidl/default/ContextHub.cpp
index bd483d7..5713a1b 100644
--- a/contexthub/aidl/default/ContextHub.cpp
+++ b/contexthub/aidl/default/ContextHub.cpp
@@ -136,4 +136,83 @@
     return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
+ScopedAStatus ContextHub::getHubs(std::vector<HubInfo>* _aidl_return) {
+    ContextHubInfo hub = {};
+    hub.name = "Mock Context Hub";
+    hub.vendor = "AOSP";
+    hub.toolchain = "n/a";
+    hub.id = kMockHubId;
+    hub.peakMips = 1;
+    hub.maxSupportedMessageLengthBytes = 4096;
+    hub.chrePlatformId = UINT64_C(0x476f6f6754000000);
+    hub.chreApiMajorVersion = 1;
+    hub.chreApiMinorVersion = 6;
+    hub.supportsReliableMessages = false;
+
+    HubInfo hubInfo1 = {};
+    hubInfo1.hubId = hub.chrePlatformId;
+    hubInfo1.hubDetails = HubInfo::HubDetails::make<HubInfo::HubDetails::Tag::contextHubInfo>(hub);
+
+    VendorHubInfo vendorHub = {};
+    vendorHub.name = "Mock Vendor Hub";
+    vendorHub.version = 42;
+
+    HubInfo hubInfo2 = {};
+    hubInfo1.hubId = UINT64_C(0x1234567812345678);
+    hubInfo1.hubDetails =
+            HubInfo::HubDetails::make<HubInfo::HubDetails::Tag::vendorHubInfo>(vendorHub);
+
+    _aidl_return->push_back(hubInfo1);
+    _aidl_return->push_back(hubInfo2);
+
+    return ScopedAStatus::ok();
+};
+
+ScopedAStatus ContextHub::getEndpoints(std::vector<EndpointInfo>* /* _aidl_return */) {
+    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ScopedAStatus ContextHub::registerEndpoint(const EndpointInfo& /* in_endpoint */) {
+    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ScopedAStatus ContextHub::unregisterEndpoint(const EndpointInfo& /* in_endpoint */) {
+    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ScopedAStatus ContextHub::registerEndpointCallback(
+        const std::shared_ptr<IEndpointCallback>& /* in_callback */) {
+    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ScopedAStatus ContextHub::requestSessionIdRange(int32_t /* in_size */,
+                                                std::vector<int32_t>* /* _aidl_return */) {
+    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ScopedAStatus ContextHub::openEndpointSession(
+        int32_t /* in_sessionId */, const EndpointId& /* in_destination */,
+        const EndpointId& /* in_initiator */,
+        const std::optional<std::string>& /* in_serviceDescriptor */) {
+    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ScopedAStatus ContextHub::sendMessageToEndpoint(int32_t /* in_sessionId */,
+                                                const Message& /* in_msg */) {
+    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ScopedAStatus ContextHub::sendMessageDeliveryStatusToEndpoint(
+        int32_t /* in_sessionId */, const MessageDeliveryStatus& /* in_msgStatus */) {
+    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ScopedAStatus ContextHub::closeEndpointSession(int32_t /* in_sessionId */, Reason /* in_reason */) {
+    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
+ScopedAStatus ContextHub::endpointSessionOpenComplete(int32_t /* in_sessionId */) {
+    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+};
+
 }  // namespace aidl::android::hardware::contexthub
diff --git a/contexthub/aidl/default/contexthub-default.xml b/contexthub/aidl/default/contexthub-default.xml
index 2f8ddc8..359bb0a 100644
--- a/contexthub/aidl/default/contexthub-default.xml
+++ b/contexthub/aidl/default/contexthub-default.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.contexthub</name>
-        <version>3</version>
+        <version>4</version>
         <interface>
             <name>IContextHub</name>
             <instance>default</instance>
diff --git a/contexthub/aidl/default/include/contexthub-impl/ContextHub.h b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
index 72e8b3b..5680a77 100644
--- a/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
+++ b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
@@ -53,6 +53,24 @@
             int32_t in_contextHubId,
             const MessageDeliveryStatus& in_messageDeliveryStatus) override;
 
+    ::ndk::ScopedAStatus getHubs(std::vector<HubInfo>* _aidl_return) override;
+    ::ndk::ScopedAStatus getEndpoints(std::vector<EndpointInfo>* _aidl_return) override;
+    ::ndk::ScopedAStatus registerEndpoint(const EndpointInfo& in_endpoint) override;
+    ::ndk::ScopedAStatus unregisterEndpoint(const EndpointInfo& in_endpoint) override;
+    ::ndk::ScopedAStatus registerEndpointCallback(
+            const std::shared_ptr<IEndpointCallback>& in_callback) override;
+    ::ndk::ScopedAStatus requestSessionIdRange(int32_t in_size,
+                                               std::vector<int32_t>* _aidl_return) override;
+    ::ndk::ScopedAStatus openEndpointSession(
+            int32_t in_sessionId, const EndpointId& in_destination, const EndpointId& in_initiator,
+            const std::optional<std::string>& in_serviceDescriptor) override;
+    ::ndk::ScopedAStatus sendMessageToEndpoint(int32_t in_sessionId,
+                                               const Message& in_msg) override;
+    ::ndk::ScopedAStatus sendMessageDeliveryStatusToEndpoint(
+            int32_t in_sessionId, const MessageDeliveryStatus& in_msgStatus) override;
+    ::ndk::ScopedAStatus closeEndpointSession(int32_t in_sessionId, Reason in_reason) override;
+    ::ndk::ScopedAStatus endpointSessionOpenComplete(int32_t in_sessionId) override;
+
   private:
     static constexpr uint32_t kMockHubId = 0;
     std::shared_ptr<IContextHubCallback> mCallback;
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index e0c6fa5..73612df 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_drm",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/drm/1.1/vts/functional/Android.bp b/drm/1.1/vts/functional/Android.bp
index b539fa2..aeb0443 100644
--- a/drm/1.1/vts/functional/Android.bp
+++ b/drm/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_drm",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/drm/1.2/vts/functional/Android.bp b/drm/1.2/vts/functional/Android.bp
index 9ceb1a3..f6fb528 100644
--- a/drm/1.2/vts/functional/Android.bp
+++ b/drm/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_drm",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/drm/1.3/vts/functional/Android.bp b/drm/1.3/vts/functional/Android.bp
index 3db23e3..a9ebd80 100644
--- a/drm/1.3/vts/functional/Android.bp
+++ b/drm/1.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_drm",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/drm/1.4/vts/functional/Android.bp b/drm/1.4/vts/functional/Android.bp
index 89edab7..0662a0f 100644
--- a/drm/1.4/vts/functional/Android.bp
+++ b/drm/1.4/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_drm",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/drm/Android.bp b/drm/Android.bp
new file mode 100644
index 0000000..35c1b03
--- /dev/null
+++ b/drm/Android.bp
@@ -0,0 +1,5 @@
+dirgroup {
+    name: "trusty_dirgroup_hardware_interfaces_drm",
+    dirs: ["."],
+    visibility: ["//trusty/vendor/google/aosp/scripts"],
+}
diff --git a/drm/aidl/Android.bp b/drm/aidl/Android.bp
index afcb603..7ee8c34 100644
--- a/drm/aidl/Android.bp
+++ b/drm/aidl/Android.bp
@@ -12,8 +12,10 @@
     vendor_available: true,
     srcs: ["android/hardware/drm/*.aidl"],
     stability: "vintf",
+    frozen: true,
     imports: [
         "android.hardware.common-V2",
+        "android.hardware.drm.common-V1",
     ],
     backend: {
         cpp: {
@@ -25,12 +27,18 @@
         ndk: {
             min_sdk_version: "34",
         },
+        rust: {
+            enabled: true,
+        },
     },
     double_loadable: true,
     versions_with_info: [
         {
             version: "1",
-            imports: ["android.hardware.common-V2"],
+            imports: [
+                "android.hardware.common-V2",
+                "android.hardware.drm.common-V1",
+            ],
         },
     ],
 
diff --git a/drm/aidl/aidl_api/android.hardware.drm/1/.hash b/drm/aidl/aidl_api/android.hardware.drm/1/.hash
index 0f8b839..9a735e9 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/1/.hash
+++ b/drm/aidl/aidl_api/android.hardware.drm/1/.hash
@@ -1,2 +1,2 @@
-3a0197fb44863256da9034c26e721b1eee12d1be
 7b4b0a0f36a7a6bb22d2016375e4a9d4a033592f
+3a0197fb44863256da9034c26e721b1eee12d1be
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/EventType.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/EventType.aidl
index 80ebb28..f09eadd 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/EventType.aidl
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/EventType.aidl
@@ -34,9 +34,9 @@
 package android.hardware.drm;
 @Backing(type="int") @VintfStability
 enum EventType {
-  PROVISION_REQUIRED = 0,
-  KEY_NEEDED = 1,
-  KEY_EXPIRED = 2,
-  VENDOR_DEFINED = 3,
-  SESSION_RECLAIMED = 4,
+  PROVISION_REQUIRED,
+  KEY_NEEDED,
+  KEY_EXPIRED,
+  VENDOR_DEFINED,
+  SESSION_RECLAIMED,
 }
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/HdcpLevel.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/HdcpLevel.aidl
deleted file mode 100644
index 5704fb0..0000000
--- a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/HdcpLevel.aidl
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.drm;
-@Backing(type="int") @VintfStability
-enum HdcpLevel {
-  HDCP_UNKNOWN = 0,
-  HDCP_NONE = 1,
-  HDCP_V1 = 2,
-  HDCP_V2 = 3,
-  HDCP_V2_1 = 4,
-  HDCP_V2_2 = 5,
-  HDCP_NO_OUTPUT = 6,
-  HDCP_V2_3 = 7,
-}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyRequestType.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyRequestType.aidl
index 34b9615..556ee38 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyRequestType.aidl
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyRequestType.aidl
@@ -34,10 +34,10 @@
 package android.hardware.drm;
 @Backing(type="int") @VintfStability
 enum KeyRequestType {
-  INITIAL = 0,
-  RENEWAL = 1,
-  RELEASE = 2,
-  UNKNOWN = 3,
-  NONE = 4,
-  UPDATE = 5,
+  INITIAL,
+  RENEWAL,
+  RELEASE,
+  UNKNOWN,
+  NONE,
+  UPDATE,
 }
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyStatusType.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyStatusType.aidl
index 261516f..5a46552 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyStatusType.aidl
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyStatusType.aidl
@@ -34,10 +34,10 @@
 package android.hardware.drm;
 @Backing(type="int") @VintfStability
 enum KeyStatusType {
-  USABLE = 0,
-  EXPIRED = 1,
-  OUTPUT_NOT_ALLOWED = 2,
-  STATUS_PENDING = 3,
-  INTERNAL_ERROR = 4,
-  USABLE_IN_FUTURE = 5,
+  USABLE,
+  EXPIRED,
+  OUTPUT_NOT_ALLOWED,
+  STATUS_PENDING,
+  INTERNAL_ERROR,
+  USABLE_IN_FUTURE,
 }
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyType.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyType.aidl
index 7a9d633..e677c86 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyType.aidl
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyType.aidl
@@ -34,7 +34,7 @@
 package android.hardware.drm;
 @Backing(type="int") @VintfStability
 enum KeyType {
-  OFFLINE = 0,
-  STREAMING = 1,
-  RELEASE = 2,
+  OFFLINE,
+  STREAMING,
+  RELEASE,
 }
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/LogPriority.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/LogPriority.aidl
index 83362c3..b77ddf6 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/LogPriority.aidl
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/LogPriority.aidl
@@ -34,12 +34,12 @@
 package android.hardware.drm;
 @Backing(type="int") @VintfStability
 enum LogPriority {
-  UNKNOWN = 0,
-  DEFAULT = 1,
-  VERBOSE = 2,
-  DEBUG = 3,
-  INFO = 4,
-  WARN = 5,
-  ERROR = 6,
-  FATAL = 7,
+  UNKNOWN,
+  DEFAULT,
+  VERBOSE,
+  DEBUG,
+  INFO,
+  WARN,
+  ERROR,
+  FATAL,
 }
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/OfflineLicenseState.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/OfflineLicenseState.aidl
index 629564d..be0e822 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/OfflineLicenseState.aidl
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/OfflineLicenseState.aidl
@@ -34,7 +34,7 @@
 package android.hardware.drm;
 @Backing(type="int") @VintfStability
 enum OfflineLicenseState {
-  UNKNOWN = 0,
-  USABLE = 1,
-  INACTIVE = 2,
+  UNKNOWN,
+  USABLE,
+  INACTIVE,
 }
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecurityLevel.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecurityLevel.aidl
index 65b2b9d..87b3641 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecurityLevel.aidl
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecurityLevel.aidl
@@ -34,11 +34,11 @@
 package android.hardware.drm;
 @Backing(type="int") @VintfStability
 enum SecurityLevel {
-  UNKNOWN = 0,
-  SW_SECURE_CRYPTO = 1,
-  SW_SECURE_DECODE = 2,
-  HW_SECURE_CRYPTO = 3,
-  HW_SECURE_DECODE = 4,
-  HW_SECURE_ALL = 5,
-  DEFAULT = 6,
+  UNKNOWN,
+  SW_SECURE_CRYPTO,
+  SW_SECURE_DECODE,
+  HW_SECURE_CRYPTO,
+  HW_SECURE_DECODE,
+  HW_SECURE_ALL,
+  DEFAULT,
 }
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Status.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Status.aidl
index c640689..a3ba6c3 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Status.aidl
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Status.aidl
@@ -34,44 +34,44 @@
 package android.hardware.drm;
 @Backing(type="int") @VintfStability
 enum Status {
-  OK = 0,
-  ERROR_DRM_NO_LICENSE = 1,
-  ERROR_DRM_LICENSE_EXPIRED = 2,
-  ERROR_DRM_SESSION_NOT_OPENED = 3,
-  ERROR_DRM_CANNOT_HANDLE = 4,
-  ERROR_DRM_INVALID_STATE = 5,
-  BAD_VALUE = 6,
-  ERROR_DRM_NOT_PROVISIONED = 7,
-  ERROR_DRM_RESOURCE_BUSY = 8,
-  ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = 9,
-  ERROR_DRM_DEVICE_REVOKED = 10,
-  ERROR_DRM_DECRYPT = 11,
-  ERROR_DRM_UNKNOWN = 12,
-  ERROR_DRM_INSUFFICIENT_SECURITY = 13,
-  ERROR_DRM_FRAME_TOO_LARGE = 14,
-  ERROR_DRM_SESSION_LOST_STATE = 15,
-  ERROR_DRM_RESOURCE_CONTENTION = 16,
-  CANNOT_DECRYPT_ZERO_SUBSAMPLES = 17,
-  CRYPTO_LIBRARY_ERROR = 18,
-  GENERAL_OEM_ERROR = 19,
-  GENERAL_PLUGIN_ERROR = 20,
-  INIT_DATA_INVALID = 21,
-  KEY_NOT_LOADED = 22,
-  LICENSE_PARSE_ERROR = 23,
-  LICENSE_POLICY_ERROR = 24,
-  LICENSE_RELEASE_ERROR = 25,
-  LICENSE_REQUEST_REJECTED = 26,
-  LICENSE_RESTORE_ERROR = 27,
-  LICENSE_STATE_ERROR = 28,
-  MALFORMED_CERTIFICATE = 29,
-  MEDIA_FRAMEWORK_ERROR = 30,
-  MISSING_CERTIFICATE = 31,
-  PROVISIONING_CERTIFICATE_ERROR = 32,
-  PROVISIONING_CONFIGURATION_ERROR = 33,
-  PROVISIONING_PARSE_ERROR = 34,
-  PROVISIONING_REQUEST_REJECTED = 35,
-  RETRYABLE_PROVISIONING_ERROR = 36,
-  SECURE_STOP_RELEASE_ERROR = 37,
-  STORAGE_READ_FAILURE = 38,
-  STORAGE_WRITE_FAILURE = 39,
+  OK,
+  ERROR_DRM_NO_LICENSE,
+  ERROR_DRM_LICENSE_EXPIRED,
+  ERROR_DRM_SESSION_NOT_OPENED,
+  ERROR_DRM_CANNOT_HANDLE,
+  ERROR_DRM_INVALID_STATE,
+  BAD_VALUE,
+  ERROR_DRM_NOT_PROVISIONED,
+  ERROR_DRM_RESOURCE_BUSY,
+  ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION,
+  ERROR_DRM_DEVICE_REVOKED,
+  ERROR_DRM_DECRYPT,
+  ERROR_DRM_UNKNOWN,
+  ERROR_DRM_INSUFFICIENT_SECURITY,
+  ERROR_DRM_FRAME_TOO_LARGE,
+  ERROR_DRM_SESSION_LOST_STATE,
+  ERROR_DRM_RESOURCE_CONTENTION,
+  CANNOT_DECRYPT_ZERO_SUBSAMPLES,
+  CRYPTO_LIBRARY_ERROR,
+  GENERAL_OEM_ERROR,
+  GENERAL_PLUGIN_ERROR,
+  INIT_DATA_INVALID,
+  KEY_NOT_LOADED,
+  LICENSE_PARSE_ERROR,
+  LICENSE_POLICY_ERROR,
+  LICENSE_RELEASE_ERROR,
+  LICENSE_REQUEST_REJECTED,
+  LICENSE_RESTORE_ERROR,
+  LICENSE_STATE_ERROR,
+  MALFORMED_CERTIFICATE,
+  MEDIA_FRAMEWORK_ERROR,
+  MISSING_CERTIFICATE,
+  PROVISIONING_CERTIFICATE_ERROR,
+  PROVISIONING_CONFIGURATION_ERROR,
+  PROVISIONING_PARSE_ERROR,
+  PROVISIONING_REQUEST_REJECTED,
+  RETRYABLE_PROVISIONING_ERROR,
+  SECURE_STOP_RELEASE_ERROR,
+  STORAGE_READ_FAILURE,
+  STORAGE_WRITE_FAILURE,
 }
diff --git a/drm/aidl/vts/Android.bp b/drm/aidl/vts/Android.bp
index 5139036..1fe0972 100644
--- a/drm/aidl/vts/Android.bp
+++ b/drm/aidl/vts/Android.bp
@@ -14,6 +14,7 @@
 // limitations under the License.
 //
 package {
+    default_team: "trendy_team_android_media_drm",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
@@ -47,6 +48,7 @@
     ],
     static_libs: [
         "android.hardware.drm@1.0-helper",
+        "android.hardware.drm.common-V1-ndk",
         "android.hardware.drm-V1-ndk",
         "android.hardware.common-V2-ndk",
         "libaidlcommonsupport",
@@ -59,13 +61,19 @@
             data: [":libvtswidevine-arm-prebuilts"],
         },
         arm64: {
-            data: [":libvtswidevine-arm64-prebuilts", ":libvtswidevine-arm-prebuilts"],
+            data: [
+                ":libvtswidevine-arm64-prebuilts",
+                ":libvtswidevine-arm-prebuilts",
+            ],
         },
         x86: {
             data: [":libvtswidevine-x86-prebuilts"],
         },
         x86_64: {
-            data: [":libvtswidevine-x86_64-prebuilts", ":libvtswidevine-x86-prebuilts"],
+            data: [
+                ":libvtswidevine-x86_64-prebuilts",
+                ":libvtswidevine-x86-prebuilts",
+            ],
         },
     },
     test_suites: [
diff --git a/drm/common/aidl/Android.bp b/drm/common/aidl/Android.bp
new file mode 100644
index 0000000..c5cb441
--- /dev/null
+++ b/drm/common/aidl/Android.bp
@@ -0,0 +1,39 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.drm.common",
+    host_supported: true,
+    vendor_available: true,
+    srcs: ["android/hardware/drm/*.aidl"],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            min_sdk_version: "34",
+        },
+        rust: {
+            enabled: true,
+        },
+    },
+    double_loadable: true,
+    versions_with_info: [
+        {
+            version: "1",
+            imports: [],
+        },
+    ],
+    frozen: true,
+
+}
diff --git a/drm/common/aidl/aidl_api/android.hardware.drm.common/1/.hash b/drm/common/aidl/aidl_api/android.hardware.drm.common/1/.hash
new file mode 100644
index 0000000..66690e1
--- /dev/null
+++ b/drm/common/aidl/aidl_api/android.hardware.drm.common/1/.hash
@@ -0,0 +1 @@
+1b5e9159609b3aa05e2c7158f3a1488fda2250d1
diff --git a/drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevel.aidl b/drm/common/aidl/aidl_api/android.hardware.drm.common/1/android/hardware/drm/HdcpLevel.aidl
similarity index 92%
rename from drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevel.aidl
rename to drm/common/aidl/aidl_api/android.hardware.drm.common/1/android/hardware/drm/HdcpLevel.aidl
index 5704fb0..118bef6 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevel.aidl
+++ b/drm/common/aidl/aidl_api/android.hardware.drm.common/1/android/hardware/drm/HdcpLevel.aidl
@@ -34,12 +34,12 @@
 package android.hardware.drm;
 @Backing(type="int") @VintfStability
 enum HdcpLevel {
-  HDCP_UNKNOWN = 0,
-  HDCP_NONE = 1,
-  HDCP_V1 = 2,
-  HDCP_V2 = 3,
-  HDCP_V2_1 = 4,
-  HDCP_V2_2 = 5,
-  HDCP_NO_OUTPUT = 6,
-  HDCP_V2_3 = 7,
+  HDCP_UNKNOWN,
+  HDCP_NONE,
+  HDCP_V1,
+  HDCP_V2,
+  HDCP_V2_1,
+  HDCP_V2_2,
+  HDCP_NO_OUTPUT,
+  HDCP_V2_3,
 }
diff --git a/drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevels.aidl b/drm/common/aidl/aidl_api/android.hardware.drm.common/1/android/hardware/drm/HdcpLevels.aidl
similarity index 100%
rename from drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevels.aidl
rename to drm/common/aidl/aidl_api/android.hardware.drm.common/1/android/hardware/drm/HdcpLevels.aidl
diff --git a/drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevel.aidl b/drm/common/aidl/aidl_api/android.hardware.drm.common/current/android/hardware/drm/HdcpLevel.aidl
similarity index 92%
copy from drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevel.aidl
copy to drm/common/aidl/aidl_api/android.hardware.drm.common/current/android/hardware/drm/HdcpLevel.aidl
index 5704fb0..118bef6 100644
--- a/drm/aidl/aidl_api/android.hardware.drm/1/android/hardware/drm/HdcpLevel.aidl
+++ b/drm/common/aidl/aidl_api/android.hardware.drm.common/current/android/hardware/drm/HdcpLevel.aidl
@@ -34,12 +34,12 @@
 package android.hardware.drm;
 @Backing(type="int") @VintfStability
 enum HdcpLevel {
-  HDCP_UNKNOWN = 0,
-  HDCP_NONE = 1,
-  HDCP_V1 = 2,
-  HDCP_V2 = 3,
-  HDCP_V2_1 = 4,
-  HDCP_V2_2 = 5,
-  HDCP_NO_OUTPUT = 6,
-  HDCP_V2_3 = 7,
+  HDCP_UNKNOWN,
+  HDCP_NONE,
+  HDCP_V1,
+  HDCP_V2,
+  HDCP_V2_1,
+  HDCP_V2_2,
+  HDCP_NO_OUTPUT,
+  HDCP_V2_3,
 }
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/HdcpLevels.aidl b/drm/common/aidl/aidl_api/android.hardware.drm.common/current/android/hardware/drm/HdcpLevels.aidl
similarity index 100%
rename from drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/HdcpLevels.aidl
rename to drm/common/aidl/aidl_api/android.hardware.drm.common/current/android/hardware/drm/HdcpLevels.aidl
diff --git a/drm/aidl/android/hardware/drm/HdcpLevel.aidl b/drm/common/aidl/android/hardware/drm/HdcpLevel.aidl
similarity index 100%
rename from drm/aidl/android/hardware/drm/HdcpLevel.aidl
rename to drm/common/aidl/android/hardware/drm/HdcpLevel.aidl
diff --git a/drm/aidl/android/hardware/drm/HdcpLevels.aidl b/drm/common/aidl/android/hardware/drm/HdcpLevels.aidl
similarity index 100%
rename from drm/aidl/android/hardware/drm/HdcpLevels.aidl
rename to drm/common/aidl/android/hardware/drm/HdcpLevels.aidl
diff --git a/dumpstate/1.0/vts/functional/Android.bp b/dumpstate/1.0/vts/functional/Android.bp
index cc0a9cd..a7ee2d8 100644
--- a/dumpstate/1.0/vts/functional/Android.bp
+++ b/dumpstate/1.0/vts/functional/Android.bp
@@ -14,6 +14,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/dumpstate/1.1/vts/functional/Android.bp b/dumpstate/1.1/vts/functional/Android.bp
index 17b412e..b2692f6 100644
--- a/dumpstate/1.1/vts/functional/Android.bp
+++ b/dumpstate/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/dumpstate/aidl/Android.bp b/dumpstate/aidl/Android.bp
index 1eb8b32..45c992a 100644
--- a/dumpstate/aidl/Android.bp
+++ b/dumpstate/aidl/Android.bp
@@ -26,6 +26,7 @@
     vendor_available: true,
     srcs: ["android/hardware/dumpstate/*.aidl"],
     stability: "vintf",
+    frozen: true,
     backend: {
         cpp: {
             enabled: false,
diff --git a/dumpstate/aidl/vts/functional/Android.bp b/dumpstate/aidl/vts/functional/Android.bp
index 5e516cf..9aa62e0 100644
--- a/dumpstate/aidl/vts/functional/Android.bp
+++ b/dumpstate/aidl/vts/functional/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/gatekeeper/1.0/vts/functional/Android.bp b/gatekeeper/1.0/vts/functional/Android.bp
index 64b3505..16e2970 100644
--- a/gatekeeper/1.0/vts/functional/Android.bp
+++ b/gatekeeper/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/gatekeeper/aidl/Android.bp b/gatekeeper/aidl/Android.bp
index 169a7d5..88c10b7 100644
--- a/gatekeeper/aidl/Android.bp
+++ b/gatekeeper/aidl/Android.bp
@@ -10,8 +10,8 @@
 aidl_interface {
     name: "android.hardware.gatekeeper",
     vendor_available: true,
-    imports: [
-        "android.hardware.security.keymint-V3",
+    defaults: [
+        "android.hardware.security.keymint-latest-defaults",
     ],
     srcs: ["android/hardware/gatekeeper/*.aidl"],
     stability: "vintf",
@@ -32,7 +32,7 @@
     versions_with_info: [
         {
             version: "1",
-            imports: ["android.hardware.security.keymint-V3"],
+            imports: ["android.hardware.security.keymint-V4"],
         },
     ],
     frozen: true,
diff --git a/gatekeeper/aidl/software/file_contexts b/gatekeeper/aidl/software/file_contexts
index 23a62ea..cc4180e 100644
--- a/gatekeeper/aidl/software/file_contexts
+++ b/gatekeeper/aidl/software/file_contexts
@@ -1,3 +1,3 @@
 (/.*)?                                                          u:object_r:vendor_file:s0
 /etc(/.*)?                                                      u:object_r:vendor_configs_file:s0
-/bin/hw/android\.hardware\.gatekeeper-service\.nonsecure        u:object_r:hal_gatekeeper_remote_exec:s0
+/bin/hw/android\.hardware\.gatekeeper-service\.nonsecure        u:object_r:hal_gatekeeper_default_exec:s0
diff --git a/gatekeeper/aidl/vts/functional/Android.bp b/gatekeeper/aidl/vts/functional/Android.bp
index 008f25c..801ee56 100644
--- a/gatekeeper/aidl/vts/functional/Android.bp
+++ b/gatekeeper/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
diff --git a/gnss/1.0/vts/functional/Android.bp b/gnss/1.0/vts/functional/Android.bp
index f27732a..b1093a6 100644
--- a/gnss/1.0/vts/functional/Android.bp
+++ b/gnss/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_location_time",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/gnss/1.1/vts/functional/Android.bp b/gnss/1.1/vts/functional/Android.bp
index f9fcbf1..65c752c 100644
--- a/gnss/1.1/vts/functional/Android.bp
+++ b/gnss/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_location_time",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/gnss/2.0/vts/functional/Android.bp b/gnss/2.0/vts/functional/Android.bp
index 0b54308..4ca3063 100644
--- a/gnss/2.0/vts/functional/Android.bp
+++ b/gnss/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_location_time",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/gnss/2.1/vts/functional/Android.bp b/gnss/2.1/vts/functional/Android.bp
index 9906b27..af66037 100644
--- a/gnss/2.1/vts/functional/Android.bp
+++ b/gnss/2.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_location_time",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl
index 8a22d6e..aaafe7f 100644
--- a/gnss/aidl/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl
@@ -217,10 +217,6 @@
      * Starts a location output stream using the IGnssCallback gnssLocationCb(), following the
      * settings from the most recent call to setPositionMode().
      *
-     * When a location output stream is in progress, calling setPositionMode() does not change the
-     * settings of the current location output stream. stop() and start() must be called to make the
-     * new settings effective.
-     *
      * This output must operate independently of any GNSS location batching operations,
      * see the IGnssBatching for details.
      */
@@ -310,10 +306,6 @@
     /**
      * Sets the GnssPositionMode parameter, its associated recurrence value, the time between fixes,
      * requested fix accuracy, time to first fix.
-     *
-     * If a location output stream is in progress, calling this method does not affect the settings
-     * of current location output stream. stop() and start() must be called to make the new settings
-     * effective.
      */
     void setPositionMode(in PositionModeOptions options);
 
diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp
index fd1d853..2bd6f07 100644
--- a/gnss/aidl/vts/Android.bp
+++ b/gnss/aidl/vts/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_location_time",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/graphics/Android.bp b/graphics/Android.bp
index cae5292..cdeb2e6 100644
--- a/graphics/Android.bp
+++ b/graphics/Android.bp
@@ -16,6 +16,23 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+aidl_interface_defaults {
+    name: "android.hardware.graphics.allocator-latest",
+    imports: [
+        "android.hardware.graphics.allocator-V2",
+    ],
+}
+
+rust_defaults {
+    name: "android.hardware.graphics.allocator-latest-rust",
+    rustlibs: [
+        "android.hardware.graphics.allocator-V2-rust",
+    ],
+    defaults: [
+        "android.hardware.graphics.common-latest-rust",
+    ],
+}
+
 cc_defaults {
     name: "android.hardware.graphics.allocator-ndk_static",
     static_libs: [
@@ -36,30 +53,53 @@
     ],
 }
 
+aidl_interface_defaults {
+    name: "android.hardware.graphics.common-latest",
+    imports: [
+        "android.hardware.graphics.common-V6",
+    ],
+}
+
+rust_defaults {
+    name: "android.hardware.graphics.common-latest-rust",
+    rustlibs: [
+        "android.hardware.graphics.common-V6-rust",
+    ],
+}
+
 cc_defaults {
     name: "android.hardware.graphics.common-ndk_static",
     static_libs: [
-        "android.hardware.graphics.common-V5-ndk",
+        "android.hardware.graphics.common-V6-ndk",
     ],
 }
 
 cc_defaults {
     name: "android.hardware.graphics.common-ndk_shared",
     shared_libs: [
-        "android.hardware.graphics.common-V5-ndk",
+        "android.hardware.graphics.common-V6-ndk",
+    ],
+}
+
+aidl_interface_defaults {
+    name: "android.hardware.graphics.composer3-latest",
+    imports: [
+        "android.hardware.graphics.composer3-V4",
     ],
 }
 
 cc_defaults {
     name: "android.hardware.graphics.composer3-ndk_static",
     static_libs: [
-        "android.hardware.graphics.composer3-V3-ndk",
+        "android.hardware.drm.common-V1-ndk",
+        "android.hardware.graphics.composer3-V4-ndk",
     ],
 }
 
 cc_defaults {
     name: "android.hardware.graphics.composer3-ndk_shared",
     shared_libs: [
-        "android.hardware.graphics.composer3-V3-ndk",
+        "android.hardware.drm.common-V1-ndk",
+        "android.hardware.graphics.composer3-V4-ndk",
     ],
 }
diff --git a/graphics/allocator/aidl/Android.bp b/graphics/allocator/aidl/Android.bp
index 7bb6b50..3f74b23 100644
--- a/graphics/allocator/aidl/Android.bp
+++ b/graphics/allocator/aidl/Android.bp
@@ -13,9 +13,11 @@
     vendor_available: true,
     double_loadable: true,
     srcs: ["android/hardware/graphics/allocator/*.aidl"],
+    defaults: [
+        "android.hardware.graphics.common-latest",
+    ],
     imports: [
         "android.hardware.common-V2",
-        "android.hardware.graphics.common-V5",
     ],
     stability: "vintf",
     backend: {
@@ -43,7 +45,7 @@
             version: "2",
             imports: [
                 "android.hardware.common-V2",
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
             ],
         },
 
diff --git a/graphics/bufferqueue/1.0/Android.bp b/graphics/bufferqueue/1.0/Android.bp
index c7c6453..87c3892 100644
--- a/graphics/bufferqueue/1.0/Android.bp
+++ b/graphics/bufferqueue/1.0/Android.bp
@@ -25,7 +25,7 @@
     gen_java: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.btservices",
+        "com.android.bt",
         "com.android.media",
         "com.android.media.swcodec",
     ],
diff --git a/graphics/bufferqueue/2.0/Android.bp b/graphics/bufferqueue/2.0/Android.bp
index e9f75c1..54f68c6 100644
--- a/graphics/bufferqueue/2.0/Android.bp
+++ b/graphics/bufferqueue/2.0/Android.bp
@@ -27,7 +27,7 @@
     gen_java: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.btservices",
+        "com.android.bt",
         "com.android.media",
         "com.android.media.swcodec",
     ],
diff --git a/graphics/common/1.0/Android.bp b/graphics/common/1.0/Android.bp
index b876bf3..1683c22 100644
--- a/graphics/common/1.0/Android.bp
+++ b/graphics/common/1.0/Android.bp
@@ -20,7 +20,7 @@
     gen_java_constants: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.btservices",
+        "com.android.bt",
         "com.android.media.swcodec",
         "test_com.android.media.swcodec",
     ],
diff --git a/graphics/common/1.1/Android.bp b/graphics/common/1.1/Android.bp
index ff6c9b7..81df887 100644
--- a/graphics/common/1.1/Android.bp
+++ b/graphics/common/1.1/Android.bp
@@ -23,7 +23,7 @@
     gen_java_constants: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.btservices",
+        "com.android.bt",
         "com.android.media.swcodec",
         "test_com.android.media.swcodec",
     ],
diff --git a/graphics/common/1.2/Android.bp b/graphics/common/1.2/Android.bp
index b4663e5..e1f4fe0 100644
--- a/graphics/common/1.2/Android.bp
+++ b/graphics/common/1.2/Android.bp
@@ -24,7 +24,7 @@
     gen_java_constants: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.btservices",
+        "com.android.bt",
         "com.android.media.swcodec",
         "test_com.android.media.swcodec",
     ],
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index c28da4c..3c75d7b 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -43,7 +43,7 @@
             enabled: true,
         },
     },
-    frozen: true,
+    frozen: false,
     versions_with_info: [
         {
             version: "1",
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
index ed84a44..54a9d8d 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
@@ -68,4 +68,5 @@
   R_16_UINT = 0x39,
   RG_1616_UINT = 0x3a,
   RGBA_10101010 = 0x3b,
+  YCBCR_P210 = 0x3c,
 }
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
index 1117504..55be4d2 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
@@ -531,4 +531,26 @@
      * interpretation is defined by the dataspace.
      */
     RGBA_10101010 = 0x3b,
+
+    /**
+     * YCBCR_P210 is a 4:2:2 YCbCr semiplanar format comprised of a WxH Y plane
+     * followed by a WxH CbCr plane. Each sample is represented by a 16-bit
+     * little-endian value, with the lower 6 bits set to zero.
+     *
+     * This format must be accepted by the allocator when used with the
+     * following usage flags:
+     *
+     *    - BufferUsage::VIDEO_*
+     *    - BufferUsage::CPU_*
+     *    - BufferUsage::GPU_TEXTURE
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     *
+     * This format is appropriate for 10bit video content.
+     *
+     * Buffers with this format must be locked with IMapper::lockYCbCr
+     * or with IMapper::lock.
+     */
+    YCBCR_P210 = 0x3c,
 }
diff --git a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
index 6a45987..9ce6eed 100644
--- a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
+++ b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
@@ -21,8 +21,7 @@
 #warn "ComposerCommandBuffer.h included without LOG_TAG"
 #endif
 
-#undef LOG_NDEBUG
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 
 #include <algorithm>
 #include <limits>
diff --git a/graphics/composer/2.2/default/Android.bp b/graphics/composer/2.2/default/Android.bp
new file mode 100644
index 0000000..5753bb0
--- /dev/null
+++ b/graphics/composer/2.2/default/Android.bp
@@ -0,0 +1,51 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: [
+        "hardware_interfaces_license",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.graphics.composer@2.2-service",
+    vendor: true,
+    relative_install_path: "hw",
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-DLOG_TAG=\"ComposerHal\"",
+    ],
+    srcs: ["service.cpp"],
+    init_rc: ["android.hardware.graphics.composer@2.2-service.rc"],
+    header_libs: ["android.hardware.graphics.composer@2.2-passthrough"],
+    shared_libs: [
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.2",
+        "android.hardware.graphics.composer@2.1-resources",
+        "android.hardware.graphics.composer@2.2-resources",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libfmq",
+        "libhardware",
+        "libhidlbase",
+        "libhwc2on1adapter",
+        "libhwc2onfbadapter",
+        "liblog",
+        "libsync",
+        "libutils",
+    ],
+}
diff --git a/graphics/composer/2.2/default/Android.mk b/graphics/composer/2.2/default/Android.mk
deleted file mode 100644
index 6f7ef85..0000000
--- a/graphics/composer/2.2/default/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.graphics.composer@2.2-service
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../NOTICE
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_CFLAGS := -Wall -Werror -DLOG_TAG=\"ComposerHal\"
-LOCAL_SRC_FILES := service.cpp
-LOCAL_INIT_RC := android.hardware.graphics.composer@2.2-service.rc
-LOCAL_HEADER_LIBRARIES := android.hardware.graphics.composer@2.2-passthrough
-LOCAL_SHARED_LIBRARIES := \
-        android.hardware.graphics.composer@2.1 \
-        android.hardware.graphics.composer@2.2 \
-        android.hardware.graphics.composer@2.1-resources \
-        android.hardware.graphics.composer@2.2-resources \
-        libbase \
-        libbinder \
-        libcutils \
-        libfmq \
-        libhardware \
-        libhidlbase \
-        libhwc2on1adapter \
-        libhwc2onfbadapter \
-        liblog \
-        libsync \
-        libutils
-
-ifdef TARGET_USES_DISPLAY_RENDER_INTENTS
-LOCAL_CFLAGS += -DUSES_DISPLAY_RENDER_INTENTS
-endif
-
-include $(BUILD_EXECUTABLE)
diff --git a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
index 00f427a..cd47374 100644
--- a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
+++ b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
@@ -20,8 +20,7 @@
 #warn "ComposerCommandBuffer.h included without LOG_TAG"
 #endif
 
-#undef LOG_NDEBUG
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 
 #include <algorithm>
 #include <limits>
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
index 7157862..3b0a597 100644
--- a/graphics/composer/2.2/utils/vts/Android.bp
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -39,6 +39,7 @@
     shared_libs: [
         "libui",
         "server_configurable_flags",
+        "libtracing_perfetto",
     ],
     static_libs: [
         "android.hardware.graphics.composer@2.1-vts",
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index bda4198..431b1b6 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -55,6 +55,7 @@
         "libui",
         "android.hardware.common-V2-ndk",
         "server_configurable_flags",
+        "libtracing_perfetto",
     ],
     static_libs: [
         "android.hardware.graphics.common@1.1",
diff --git a/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
index 5e9a287..1a9276c 100644
--- a/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
+++ b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
@@ -20,8 +20,7 @@
 #warn "ComposerCommandBuffer.h included without LOG_TAG"
 #endif
 
-#undef LOG_NDEBUG
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 
 #include <android/hardware/graphics/composer/2.3/IComposer.h>
 #include <android/hardware/graphics/composer/2.3/IComposerClient.h>
diff --git a/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h b/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h
index eb35e5c..e981da6 100644
--- a/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h
+++ b/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h
@@ -20,8 +20,7 @@
 #warn "ComposerCommandBuffer.h included without LOG_TAG"
 #endif
 
-#undef LOG_NDEBUG
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 
 #include <android/hardware/graphics/composer/2.4/IComposer.h>
 #include <android/hardware/graphics/composer/2.4/IComposerClient.h>
diff --git a/graphics/composer/aidl/Android.bp b/graphics/composer/aidl/Android.bp
index c4e6878..719318a 100644
--- a/graphics/composer/aidl/Android.bp
+++ b/graphics/composer/aidl/Android.bp
@@ -29,14 +29,17 @@
     host_supported: true,
     vendor_available: true,
     double_loadable: true,
-    frozen: true,
+    frozen: false,
     srcs: [
         "android/hardware/graphics/composer3/*.aidl",
     ],
     stability: "vintf",
+    defaults: [
+        "android.hardware.graphics.common-latest",
+    ],
     imports: [
-        "android.hardware.graphics.common-V5",
         "android.hardware.common-V2",
+        "android.hardware.drm.common-V1",
     ],
     backend: {
         cpp: {
@@ -56,21 +59,21 @@
         {
             version: "1",
             imports: [
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
                 "android.hardware.common-V2",
             ],
         },
         {
             version: "2",
             imports: [
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
                 "android.hardware.common-V2",
             ],
         },
         {
             version: "3",
             imports: [
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
                 "android.hardware.common-V2",
             ],
         },
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandResultPayload.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandResultPayload.aidl
index 6892f06..0fff523 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandResultPayload.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandResultPayload.aidl
@@ -41,4 +41,5 @@
   android.hardware.graphics.composer3.ReleaseFences releaseFences;
   android.hardware.graphics.composer3.PresentOrValidate presentOrValidateResult;
   android.hardware.graphics.composer3.ClientTargetPropertyWithBrightness clientTargetProperty;
+  android.hardware.graphics.composer3.DisplayLuts displayLuts;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/NextEnrollment.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayLuts.aidl
similarity index 84%
rename from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayLuts.aidl
index 75ed070..327e84c 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayLuts.aidl
@@ -5,7 +5,7 @@
  * 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
+ *     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,
@@ -31,11 +31,13 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.graphics.composer3;
 @VintfStability
-parcelable NextEnrollment {
-  int id;
-  android.hardware.biometrics.fingerprint.EnrollmentProgressStep[] progressSteps;
-  boolean result = true;
+parcelable DisplayLuts {
+  long display;
+  android.hardware.graphics.composer3.DisplayLuts.LayerLut[] layerLuts;
+  parcelable LayerLut {
+    long layer;
+    android.hardware.graphics.composer3.Lut lut;
+  }
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerCallback.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerCallback.aidl
index e64bd52..cd27360 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerCallback.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerCallback.aidl
@@ -45,4 +45,5 @@
   oneway void onVsyncIdle(long display);
   oneway void onRefreshRateChangedDebug(in android.hardware.graphics.composer3.RefreshRateChangedDebugData data);
   void onHotplugEvent(long display, android.hardware.graphics.common.DisplayHotplugEvent event);
+  oneway void onHdcpLevelsChanged(long display, in android.hardware.drm.HdcpLevels levels);
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
index 87c8c18..8b2b13c 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
@@ -57,4 +57,5 @@
   @nullable int[] bufferSlotsToClear;
   android.hardware.graphics.composer3.LayerLifecycleBatchCommandType layerLifecycleBatchCommandType;
   int newBufferSlotCount;
+  @nullable android.hardware.graphics.composer3.Lut[] luts;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Lut.aidl
similarity index 85%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
copy to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Lut.aidl
index 173ac17..5fae35b 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Lut.aidl
@@ -5,7 +5,7 @@
  * 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
+ *     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,
@@ -31,10 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.graphics.composer3;
 @VintfStability
-parcelable EnrollmentProgressStep {
-  int durationMs;
-  android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes;
+parcelable Lut {
+  @nullable ParcelFileDescriptor pfd;
+  android.hardware.graphics.composer3.LutProperties lutProperties;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/NextEnrollment.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl
similarity index 79%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
copy to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl
index 75ed070..5edceb5 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl
@@ -5,7 +5,7 @@
  * 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
+ *     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,
@@ -31,11 +31,20 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.graphics.composer3;
 @VintfStability
-parcelable NextEnrollment {
-  int id;
-  android.hardware.biometrics.fingerprint.EnrollmentProgressStep[] progressSteps;
-  boolean result = true;
+parcelable LutProperties {
+  android.hardware.graphics.composer3.LutProperties.Dimension dimension;
+  long size;
+  android.hardware.graphics.composer3.LutProperties.SamplingKey[] samplingKeys;
+  @VintfStability
+  enum Dimension {
+    ONE_D = 1,
+    THREE_D = 3,
+  }
+  @VintfStability
+  enum SamplingKey {
+    RGB,
+    MAX_RGB,
+  }
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/OverlayProperties.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/OverlayProperties.aidl
index 7d31ea3..dae78fd 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/OverlayProperties.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/OverlayProperties.aidl
@@ -36,6 +36,7 @@
 parcelable OverlayProperties {
   android.hardware.graphics.composer3.OverlayProperties.SupportedBufferCombinations[] combinations;
   boolean supportMixedColorSpaces;
+  @nullable android.hardware.graphics.composer3.LutProperties[] lutProperties;
   parcelable SupportedBufferCombinations {
     android.hardware.graphics.common.PixelFormat[] pixelFormats;
     android.hardware.graphics.common.Dataspace[] standards;
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl
index 99c91aa..94fc3d0 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl
@@ -19,6 +19,7 @@
 import android.hardware.graphics.composer3.ChangedCompositionTypes;
 import android.hardware.graphics.composer3.ClientTargetPropertyWithBrightness;
 import android.hardware.graphics.composer3.CommandError;
+import android.hardware.graphics.composer3.DisplayLuts;
 import android.hardware.graphics.composer3.DisplayRequest;
 import android.hardware.graphics.composer3.PresentFence;
 import android.hardware.graphics.composer3.PresentOrValidate;
@@ -96,4 +97,13 @@
      * the SDR buffers when an HDR layer is simultaneously device-composited.
      */
     ClientTargetPropertyWithBrightness clientTargetProperty;
+
+    /**
+     * Sets the Lut(s) for the layers.
+     *
+     * HWC should only request Lut(s) if SurfaceFlinger does not send the Lut(s) to the HWC.
+     * The main use-case is like HDR10+ or Dolby Vision where there is no Lut to send from
+     * SurfaceFlinger.
+     */
+    DisplayLuts displayLuts;
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayLuts.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayLuts.aidl
new file mode 100644
index 0000000..ac0a606
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayLuts.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.Lut;
+
+/**
+ * LUT (Look-Up Table) Interface for Color Transformation.
+ *
+ * This interface allows the HWC (Hardware Composer) to define and communicate Luts
+ * to SurfaceFlinger.
+ */
+@VintfStability
+parcelable DisplayLuts {
+    /**
+     * The display which the layerLuts list is for.
+     */
+    long display;
+
+    parcelable LayerLut {
+        /**
+         * The layer that the HWC is requesting a LUT to be applied during GPU composition.
+         */
+        long layer;
+        /**
+         * A Lut specified by the HWC for given HDR layers that don't have Luts provided.
+         */
+        Lut lut;
+    }
+
+    LayerLut[] layerLuts;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl
index 96eccd7..a1d61fd 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.graphics.composer3;
 
+import android.hardware.drm.HdcpLevels;
 import android.hardware.graphics.common.DisplayHotplugEvent;
 import android.hardware.graphics.composer3.RefreshRateChangedDebugData;
 import android.hardware.graphics.composer3.VsyncPeriodChangeTimeline;
@@ -139,4 +140,12 @@
      * @param event is the type of event that occurred.
      */
     void onHotplugEvent(long display, DisplayHotplugEvent event);
+
+    /**
+     * Notify the client the HDCP levels of the display changed.
+     *
+     * @param display is the display whose HDCP levels have changed.
+     * @param levels is the new HDCP levels.
+     */
+    oneway void onHdcpLevelsChanged(long display, in HdcpLevels levels);
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
index e961c48..bf4f504 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
@@ -24,6 +24,7 @@
 import android.hardware.graphics.composer3.Color;
 import android.hardware.graphics.composer3.LayerBrightness;
 import android.hardware.graphics.composer3.LayerLifecycleBatchCommandType;
+import android.hardware.graphics.composer3.Lut;
 import android.hardware.graphics.composer3.ParcelableBlendMode;
 import android.hardware.graphics.composer3.ParcelableComposition;
 import android.hardware.graphics.composer3.ParcelableDataspace;
@@ -279,4 +280,9 @@
      * Specifies the number of buffer slot to be reserved.
      */
     int newBufferSlotCount;
+
+    /**
+     * Sets the lut(s) for the layer.
+     */
+    @nullable Lut[] luts;
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Lut.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Lut.aidl
new file mode 100644
index 0000000..abfeb14
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Lut.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+import android.hardware.graphics.composer3.LutProperties;
+
+/**
+ * LUT (Look-Up Table) Interface for Color Transformation.
+ *
+ * This interface allows the HWC (Hardware Composer) to define and communicate LUTs
+ * with SurfaceFlinger.
+ */
+
+@VintfStability
+parcelable Lut {
+    /**
+     * A handle to a memory region.
+     * If the file descriptor is not set, this means that the HWC doesn't specify a Lut.
+     *
+     * When specifying a Lut, the HWC is required to follow the instructions as below:
+     * 1. use `memfd_create` to create a shared memory segment
+     *    with the size specified in lutProperties.
+     * 2. use `mmap` to map the shared memory segment into its own virtual address space.
+     *    PROT_READ/PROT_WRITE recommended for prot argument.
+     *
+     * For data precision, 32-bit float is used to specify a Lut by both the HWC and
+     * the platform.
+     *
+     * For unflattening/flattening 3D Lut(s), the algorithm below should be observed
+     * by both the HWC and the platform.
+     * Assuming that we have a 3D array `ORIGINAL[WIDTH, HEIGHT, DEPTH]`, we would turn it into
+     * `FLAT[WIDTH * HEIGHT * DEPTH]` by
+     *
+     * `FLAT[z + DEPTH * (y + HEIGHT * x)] = ORIGINAL[x, y, z]`
+     */
+    @nullable ParcelFileDescriptor pfd;
+
+    /**
+     * The properties of the Lut.
+     */
+    LutProperties lutProperties;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl
new file mode 100644
index 0000000..47ec390
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer3;
+
+/**
+ * The properties of the LUT (Look-Up Table).
+ */
+@VintfStability
+parcelable LutProperties {
+    /**
+     * The dimension of the Lut.
+     * Either 1d or 3d.
+     */
+    @VintfStability enum Dimension { ONE_D = 1, THREE_D = 3 }
+    Dimension dimension;
+
+    /**
+     * The size of the Lut.
+     * This refers to the length of a 1D Lut, or the grid size of a 3D one.
+     */
+    long size;
+
+    /**
+     * SamplingKey is about how a Lut can be sampled.
+     * A Lut can be sampled in more than one way,
+     * but only one sampling method is used at one time.
+     *
+     * The implementations should use a sampling strategy
+     * at least as good as linear sampling.
+     */
+    // TODO(b/358422255): add sampling ways
+    @VintfStability enum SamplingKey { RGB, MAX_RGB }
+    SamplingKey[] samplingKeys;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/OverlayProperties.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/OverlayProperties.aidl
index c25eea4..b97cdcc 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/OverlayProperties.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/OverlayProperties.aidl
@@ -16,6 +16,8 @@
 
 package android.hardware.graphics.composer3;
 
+import android.hardware.graphics.composer3.LutProperties;
+
 @VintfStability
 parcelable OverlayProperties {
     parcelable SupportedBufferCombinations {
@@ -42,4 +44,8 @@
     // True if the DPU is able to color manage at least two overlays
     // with different input colorspaces, false otherwise.
     boolean supportMixedColorSpaces;
+
+    // Array of lut properties in order that the HWC supports.
+    // The list accepts 1D lut(s) and 3D lut(s).
+    @nullable LutProperties[] lutProperties;
 }
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
index 76ba24b..331d717 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
@@ -27,9 +27,8 @@
 #include <string.h>
 
 #include <aidl/android/hardware/graphics/composer3/ClientTargetProperty.h>
-#include <aidl/android/hardware/graphics/composer3/Composition.h>
 #include <aidl/android/hardware/graphics/composer3/CommandResultPayload.h>
-
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
 
 #include <log/log.h>
 #include <sync/sync.h>
@@ -84,6 +83,10 @@
                     parseSetClientTargetProperty(std::move(
                             result.get<CommandResultPayload::Tag::clientTargetProperty>()));
                     break;
+                case CommandResultPayload::Tag::displayLuts:
+                    parseSetDisplayLuts(
+                            std::move(result.get<CommandResultPayload::Tag::displayLuts>()));
+                    break;
             }
         }
     }
@@ -182,6 +185,20 @@
         return std::move(data.clientTargetProperty);
     }
 
+    // Get the lut(s) requested by hardware composer.
+    std::vector<DisplayLuts::LayerLut> takeDisplayLuts(int64_t display) {
+        LOG_ALWAYS_FATAL_IF(mDisplay && display != *mDisplay);
+        auto found = mReturnData.find(display);
+
+        // If not found, return the empty vector
+        if (found == mReturnData.end()) {
+            return {};
+        }
+
+        ReturnData& data = found->second;
+        return std::move(data.layerLuts);
+    }
+
   private:
     void resetData() {
         mErrors.clear();
@@ -227,6 +244,18 @@
         data.clientTargetProperty = std::move(clientTargetProperty);
     }
 
+    void parseSetDisplayLuts(DisplayLuts&& displayLuts) {
+        LOG_ALWAYS_FATAL_IF(mDisplay && displayLuts.display != *mDisplay);
+        auto& data = mReturnData[displayLuts.display];
+        for (auto& layerLut : displayLuts.layerLuts) {
+            if (layerLut.lut.pfd.get() >= 0) {
+                data.layerLuts.push_back(
+                        {layerLut.layer, Lut{ndk::ScopedFileDescriptor(layerLut.lut.pfd.release()),
+                                             layerLut.lut.lutProperties}});
+            }
+        }
+    }
+
     struct ReturnData {
         DisplayRequest displayRequests;
         std::vector<ChangedCompositionLayer> changedLayers;
@@ -238,6 +267,7 @@
                 .clientTargetProperty = {common::PixelFormat::RGBA_8888, Dataspace::UNKNOWN},
                 .brightness = 1.f,
         };
+        std::vector<DisplayLuts::LayerLut> layerLuts;
     };
 
     std::vector<CommandError> mErrors;
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
index a1ccbfe..02fb3aa 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
@@ -30,6 +30,7 @@
 #include <aidl/android/hardware/graphics/composer3/DisplayBrightness.h>
 #include <aidl/android/hardware/graphics/composer3/LayerBrightness.h>
 #include <aidl/android/hardware/graphics/composer3/LayerLifecycleBatchCommandType.h>
+#include <aidl/android/hardware/graphics/composer3/Lut.h>
 #include <aidl/android/hardware/graphics/composer3/PerFrameMetadata.h>
 #include <aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.h>
 
@@ -245,6 +246,15 @@
         getLayerCommand(display, layer).blockingRegion.emplace(blocking.begin(), blocking.end());
     }
 
+    void setLayerLuts(int64_t display, int64_t layer, std::vector<Lut>& luts) {
+        std::vector<std::optional<Lut>> currentLuts;
+        for (auto& lut : luts) {
+            currentLuts.push_back(std::make_optional<Lut>(
+                    {ndk::ScopedFileDescriptor(lut.pfd.release()), lut.lutProperties}));
+        }
+        getLayerCommand(display, layer).luts.emplace(std::move(currentLuts));
+    }
+
     std::vector<DisplayCommand> takePendingCommands() {
         flushLayerCommand();
         flushDisplayCommand();
diff --git a/graphics/composer/aidl/vts/Android.bp b/graphics/composer/aidl/vts/Android.bp
index 3464fe9..894ca52 100644
--- a/graphics/composer/aidl/vts/Android.bp
+++ b/graphics/composer/aidl/vts/Android.bp
@@ -57,6 +57,7 @@
         "libprocessgroup",
         "libvndksupport",
         "server_configurable_flags",
+        "libtracing_perfetto",
     ],
     header_libs: [
         "android.hardware.graphics.composer3-command-buffer",
@@ -65,6 +66,7 @@
         "android.hardware.graphics.common@1.2",
         "android.hardware.common-V2-ndk",
         "android.hardware.common.fmq-V1-ndk",
+        "android.hardware.drm.common-V1-ndk",
         "libaidlcommonsupport",
         "libarect",
         "libbase",
diff --git a/graphics/composer/aidl/vts/GraphicsComposerCallback.cpp b/graphics/composer/aidl/vts/GraphicsComposerCallback.cpp
index 544f692..1f7972c 100644
--- a/graphics/composer/aidl/vts/GraphicsComposerCallback.cpp
+++ b/graphics/composer/aidl/vts/GraphicsComposerCallback.cpp
@@ -208,4 +208,15 @@
     }
 }
 
+::ndk::ScopedAStatus GraphicsComposerCallback::onHdcpLevelsChanged(
+        int64_t in_display, const ::aidl::android::hardware::drm::HdcpLevels&) {
+    std::scoped_lock lock(mMutex);
+
+    const auto it = std::find(mDisplays.begin(), mDisplays.end(), in_display);
+    if (it != mDisplays.end()) {
+        mHdcpLevelChangedCount++;
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::graphics::composer3::vts
diff --git a/graphics/composer/aidl/vts/GraphicsComposerCallback.h b/graphics/composer/aidl/vts/GraphicsComposerCallback.h
index 7a8d4a3..97f8e2b 100644
--- a/graphics/composer/aidl/vts/GraphicsComposerCallback.h
+++ b/graphics/composer/aidl/vts/GraphicsComposerCallback.h
@@ -65,6 +65,8 @@
             const RefreshRateChangedDebugData&) override;
     virtual ::ndk::ScopedAStatus onHotplugEvent(int64_t in_display,
                                                 common::DisplayHotplugEvent) override;
+    virtual ::ndk::ScopedAStatus onHdcpLevelsChanged(
+            int64_t in_display, const ::aidl::android::hardware::drm::HdcpLevels&) override;
 
     mutable std::mutex mMutex;
     // the set of all currently connected displays
@@ -88,6 +90,7 @@
     int32_t mInvalidVsyncPeriodChangeCount GUARDED_BY(mMutex) = 0;
     int32_t mInvalidSeamlessPossibleCount GUARDED_BY(mMutex) = 0;
     int32_t mInvalidRefreshRateDebugEnabledCallbackCount GUARDED_BY(mMutex) = 0;
+    int32_t mHdcpLevelChangedCount GUARDED_BY(mMutex) = 0;
 };
 
 }  // namespace aidl::android::hardware::graphics::composer3::vts
diff --git a/graphics/composer/aidl/vts/ReadbackVts.cpp b/graphics/composer/aidl/vts/ReadbackVts.cpp
index 283b8ce..9d5928d 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.cpp
+++ b/graphics/composer/aidl/vts/ReadbackVts.cpp
@@ -16,6 +16,7 @@
 
 #include "ReadbackVts.h"
 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
+#include <cmath>
 #include "RenderEngineVts.h"
 #include "renderengine/ExternalTexture.h"
 #include "renderengine/impl/ExternalTexture.h"
@@ -106,37 +107,72 @@
     return layerSettings;
 }
 
-int32_t ReadbackHelper::GetBytesPerPixel(common::PixelFormat pixelFormat) {
+int32_t ReadbackHelper::GetBitsPerChannel(common::PixelFormat pixelFormat) {
     switch (pixelFormat) {
+        case common::PixelFormat::RGBA_1010102:
+            return 10;
         case common::PixelFormat::RGBA_8888:
-            return 4;
         case common::PixelFormat::RGB_888:
-            return 3;
+            return 8;
         default:
             return -1;
     }
 }
 
-void ReadbackHelper::fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData,
+int32_t ReadbackHelper::GetAlphaBits(common::PixelFormat pixelFormat) {
+    switch (pixelFormat) {
+        case common::PixelFormat::RGBA_8888:
+            return 8;
+        case common::PixelFormat::RGBA_1010102:
+            return 2;
+        case common::PixelFormat::RGB_888:
+            return 0;
+        default:
+            return -1;
+    }
+}
+
+void ReadbackHelper::fillBuffer(uint32_t width, uint32_t height, uint32_t stride,
+                                int32_t bytesPerPixel, void* bufferData,
                                 common::PixelFormat pixelFormat,
                                 std::vector<Color> desiredPixelColors) {
     ASSERT_TRUE(pixelFormat == common::PixelFormat::RGB_888 ||
-                pixelFormat == common::PixelFormat::RGBA_8888);
-    int32_t bytesPerPixel = GetBytesPerPixel(pixelFormat);
+                pixelFormat == common::PixelFormat::RGBA_8888 ||
+                pixelFormat == common::PixelFormat::RGBA_1010102);
+    int32_t bitsPerChannel = GetBitsPerChannel(pixelFormat);
+    int32_t alphaBits = GetAlphaBits(pixelFormat);
+    ASSERT_NE(-1, alphaBits);
+    ASSERT_NE(-1, bitsPerChannel);
     ASSERT_NE(-1, bytesPerPixel);
-    for (int row = 0; row < height; row++) {
-        for (int col = 0; col < width; col++) {
-            auto pixel = row * static_cast<int32_t>(width) + col;
+
+    uint32_t maxValue = (1 << bitsPerChannel) - 1;
+    uint32_t maxAlphaValue = (1 << alphaBits) - 1;
+    for (uint32_t row = 0; row < height; row++) {
+        for (uint32_t col = 0; col < width; col++) {
+            auto pixel = row * width + col;
             Color srcColor = desiredPixelColors[static_cast<size_t>(pixel)];
 
-            int offset = (row * static_cast<int32_t>(stride) + col) * bytesPerPixel;
-            uint8_t* pixelColor = (uint8_t*)bufferData + offset;
-            pixelColor[0] = static_cast<uint8_t>(std::round(255.0f * srcColor.r));
-            pixelColor[1] = static_cast<uint8_t>(std::round(255.0f * srcColor.g));
-            pixelColor[2] = static_cast<uint8_t>(std::round(255.0f * srcColor.b));
+            uint32_t offset = (row * stride + col) * static_cast<uint32_t>(bytesPerPixel);
 
-            if (bytesPerPixel == 4) {
-                pixelColor[3] = static_cast<uint8_t>(std::round(255.0f * srcColor.a));
+            uint32_t* pixelStart = (uint32_t*)((uint8_t*)bufferData + offset);
+
+            uint32_t red = static_cast<uint32_t>(std::round(maxValue * srcColor.r));
+            uint32_t green = static_cast<uint32_t>(std::round(maxValue * srcColor.g));
+            uint32_t blue = static_cast<uint32_t>(std::round(maxValue * srcColor.b));
+
+            // Boo we're not word aligned so special case this.
+            if (pixelFormat == common::PixelFormat::RGB_888) {
+                uint8_t* pixelColor = (uint8_t*)pixelStart;
+                pixelColor[0] = static_cast<uint8_t>(red);
+                pixelColor[1] = static_cast<uint8_t>(green);
+                pixelColor[2] = static_cast<uint8_t>(blue);
+            } else {
+                uint32_t alpha = static_cast<uint32_t>(std::round(maxAlphaValue * srcColor.a));
+                uint32_t color = (alpha << (32 - alphaBits)) |
+                                 (blue << (32 - alphaBits - bitsPerChannel)) |
+                                 (green << (32 - alphaBits - bitsPerChannel * 2)) |
+                                 (red << (32 - alphaBits - bitsPerChannel * 3));
+                *pixelStart = color;
             }
         }
     }
@@ -165,7 +201,8 @@
 bool ReadbackHelper::readbackSupported(const common::PixelFormat& pixelFormat,
                                        const common::Dataspace& dataspace) {
     if (pixelFormat != common::PixelFormat::RGB_888 &&
-        pixelFormat != common::PixelFormat::RGBA_8888) {
+        pixelFormat != common::PixelFormat::RGBA_8888 &&
+        pixelFormat != common::PixelFormat::RGBA_1010102) {
         return false;
     }
     if (std::find(dataspaces.begin(), dataspaces.end(), dataspace) == dataspaces.end()) {
@@ -175,36 +212,110 @@
 }
 
 void ReadbackHelper::compareColorBuffers(const std::vector<Color>& expectedColors, void* bufferData,
-                                         const uint32_t stride, const uint32_t width,
-                                         const uint32_t height, common::PixelFormat pixelFormat) {
-    const int32_t bytesPerPixel = ReadbackHelper::GetBytesPerPixel(pixelFormat);
-    ASSERT_NE(-1, bytesPerPixel);
-    for (int row = 0; row < height; row++) {
-        for (int col = 0; col < width; col++) {
-            auto pixel = row * static_cast<int32_t>(width) + col;
-            int offset = (row * static_cast<int32_t>(stride) + col) * bytesPerPixel;
-            uint8_t* pixelColor = (uint8_t*)bufferData + offset;
+                                         const uint32_t stride, int32_t bytesPerPixel,
+                                         const uint32_t width, const uint32_t height,
+                                         common::PixelFormat pixelFormat) {
+    int32_t bitsPerChannel = GetBitsPerChannel(pixelFormat);
+    int32_t alphaBits = GetAlphaBits(pixelFormat);
+    ASSERT_GT(bytesPerPixel, 0);
+    ASSERT_NE(-1, alphaBits);
+    ASSERT_NE(-1, bitsPerChannel);
+    uint32_t maxValue = (1 << bitsPerChannel) - 1;
+    uint32_t maxAlphaValue = (1 << alphaBits) - 1;
+    for (uint32_t row = 0; row < height; row++) {
+        for (uint32_t col = 0; col < width; col++) {
+            auto pixel = row * width + col;
             const Color expectedColor = expectedColors[static_cast<size_t>(pixel)];
-            ASSERT_EQ(std::round(255.0f * expectedColor.r), pixelColor[0]);
-            ASSERT_EQ(std::round(255.0f * expectedColor.g), pixelColor[1]);
-            ASSERT_EQ(std::round(255.0f * expectedColor.b), pixelColor[2]);
+
+            uint32_t offset = (row * stride + col) * static_cast<uint32_t>(bytesPerPixel);
+            uint32_t* pixelStart = (uint32_t*)((uint8_t*)bufferData + offset);
+
+            uint32_t expectedRed = static_cast<uint32_t>(std::round(maxValue * expectedColor.r));
+            uint32_t expectedGreen = static_cast<uint32_t>(std::round(maxValue * expectedColor.g));
+            uint32_t expectedBlue = static_cast<uint32_t>(std::round(maxValue * expectedColor.b));
+
+            // Boo we're not word aligned so special case this.
+            if (pixelFormat == common::PixelFormat::RGB_888) {
+                uint8_t* pixelColor = (uint8_t*)pixelStart;
+                ASSERT_EQ(pixelColor[0], static_cast<uint8_t>(expectedRed))
+                        << "Red channel mismatch at (" << row << ", " << col << ")";
+                ASSERT_EQ(pixelColor[1], static_cast<uint8_t>(expectedGreen))
+                        << "Green channel mismatch at (" << row << ", " << col << ")";
+                ASSERT_EQ(pixelColor[2], static_cast<uint8_t>(expectedBlue))
+                        << "Blue channel mismatch at (" << row << ", " << col << ")";
+            } else {
+                uint32_t expectedAlpha =
+                        static_cast<uint32_t>(std::round(maxAlphaValue * expectedColor.a));
+
+                uint32_t actualRed =
+                        (*pixelStart >> (32 - alphaBits - bitsPerChannel * 3)) & maxValue;
+                uint32_t actualGreen =
+                        (*pixelStart >> (32 - alphaBits - bitsPerChannel * 2)) & maxValue;
+                uint32_t actualBlue = (*pixelStart >> (32 - alphaBits - bitsPerChannel)) & maxValue;
+                uint32_t actualAlpha = (*pixelStart >> (32 - alphaBits)) & maxAlphaValue;
+
+                ASSERT_EQ(expectedRed, actualRed)
+                        << "Red channel mismatch at (" << row << ", " << col << ")";
+                ASSERT_EQ(expectedGreen, actualGreen)
+                        << "Green channel mismatch at (" << row << ", " << col << ")";
+                ASSERT_EQ(expectedBlue, actualBlue)
+                        << "Blue channel mismatch at (" << row << ", " << col << ")";
+            }
         }
     }
 }
 
 void ReadbackHelper::compareColorBuffers(void* expectedBuffer, void* actualBuffer,
-                                         const uint32_t stride, const uint32_t width,
-                                         const uint32_t height, common::PixelFormat pixelFormat) {
-    const int32_t bytesPerPixel = ReadbackHelper::GetBytesPerPixel(pixelFormat);
-    ASSERT_NE(-1, bytesPerPixel);
-    for (int row = 0; row < height; row++) {
-        for (int col = 0; col < width; col++) {
-            int offset = (row * static_cast<int32_t>(stride) + col) * bytesPerPixel;
-            uint8_t* expectedColor = (uint8_t*)expectedBuffer + offset;
-            uint8_t* actualColor = (uint8_t*)actualBuffer + offset;
-            ASSERT_EQ(expectedColor[0], actualColor[0]);
-            ASSERT_EQ(expectedColor[1], actualColor[1]);
-            ASSERT_EQ(expectedColor[2], actualColor[2]);
+                                         const uint32_t stride, int32_t bytesPerPixel,
+                                         const uint32_t width, const uint32_t height,
+                                         common::PixelFormat pixelFormat) {
+    int32_t bitsPerChannel = GetBitsPerChannel(pixelFormat);
+    int32_t alphaBits = GetAlphaBits(pixelFormat);
+    ASSERT_GT(bytesPerPixel, 0);
+    ASSERT_NE(-1, alphaBits);
+    ASSERT_NE(-1, bitsPerChannel);
+    uint32_t maxValue = (1 << bitsPerChannel) - 1;
+    uint32_t maxAlphaValue = (1 << alphaBits) - 1;
+    for (uint32_t row = 0; row < height; row++) {
+        for (uint32_t col = 0; col < width; col++) {
+            uint32_t offset = (row * stride + col) * static_cast<uint32_t>(bytesPerPixel);
+            uint32_t* expectedStart = (uint32_t*)((uint8_t*)expectedBuffer + offset);
+            uint32_t* actualStart = (uint32_t*)((uint8_t*)actualBuffer + offset);
+
+            // Boo we're not word aligned so special case this.
+            if (pixelFormat == common::PixelFormat::RGB_888) {
+                uint8_t* expectedPixel = (uint8_t*)expectedStart;
+                uint8_t* actualPixel = (uint8_t*)actualStart;
+                ASSERT_EQ(actualPixel[0], expectedPixel[0])
+                        << "Red channel mismatch at (" << row << ", " << col << ")";
+                ASSERT_EQ(actualPixel[1], expectedPixel[1])
+                        << "Green channel mismatch at (" << row << ", " << col << ")";
+                ASSERT_EQ(actualPixel[2], expectedPixel[2])
+                        << "Blue channel mismatch at (" << row << ", " << col << ")";
+            } else {
+                uint32_t expectedRed =
+                        (*expectedStart >> (32 - alphaBits - bitsPerChannel * 3)) & maxValue;
+                uint32_t expectedGreen =
+                        (*expectedStart >> (32 - alphaBits - bitsPerChannel * 2)) & maxValue;
+                uint32_t expectedBlue =
+                        (*expectedStart >> (32 - alphaBits - bitsPerChannel)) & maxValue;
+                uint32_t expectedAlpha = (*expectedStart >> (32 - alphaBits)) & maxAlphaValue;
+
+                uint32_t actualRed =
+                        (*actualStart >> (32 - alphaBits - bitsPerChannel * 3)) & maxValue;
+                uint32_t actualGreen =
+                        (*actualStart >> (32 - alphaBits - bitsPerChannel * 2)) & maxValue;
+                uint32_t actualBlue =
+                        (*actualStart >> (32 - alphaBits - bitsPerChannel)) & maxValue;
+                uint32_t actualAlpha = (*actualStart >> (32 - alphaBits)) & maxAlphaValue;
+
+                ASSERT_EQ(expectedRed, actualRed)
+                        << "Red channel mismatch at (" << row << ", " << col << ")";
+                ASSERT_EQ(expectedGreen, actualGreen)
+                        << "Green channel mismatch at (" << row << ", " << col << ")";
+                ASSERT_EQ(expectedBlue, actualBlue)
+                        << "Blue channel mismatch at (" << row << ", " << col << ")";
+            }
         }
     }
 }
@@ -258,12 +369,13 @@
     auto status = mGraphicBuffer->lockAsync(mUsage, mAccessRegion, &bufData, dup(bufferFence.get()),
                                             &bytesPerPixel, &bytesPerStride);
     EXPECT_EQ(::android::OK, status);
-    ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
+    ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888 ||
+                mPixelFormat == PixelFormat::RGBA_1010102);
     const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
                                     ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
                                     : mGraphicBuffer->getStride();
-    ReadbackHelper::compareColorBuffers(expectedColors, bufData, stride, mWidth, mHeight,
-                                        mPixelFormat);
+    ReadbackHelper::compareColorBuffers(expectedColors, bufData, stride, bytesPerPixel, mWidth,
+                                        mHeight, mPixelFormat);
     status = mGraphicBuffer->unlock();
     EXPECT_EQ(::android::OK, status);
 }
@@ -353,8 +465,8 @@
                                     ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
                                     : mGraphicBuffer->getStride();
     EXPECT_EQ(::android::OK, status);
-    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mWidth, mHeight, stride, bufData,
-                                                       mPixelFormat, expectedColors));
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mWidth, mHeight, stride, bytesPerPixel,
+                                                       bufData, mPixelFormat, expectedColors));
 
     const auto unlockStatus = mGraphicBuffer->unlockAsync(&mFillFence);
     ASSERT_EQ(::android::OK, unlockStatus);
diff --git a/graphics/composer/aidl/vts/ReadbackVts.h b/graphics/composer/aidl/vts/ReadbackVts.h
index 8ac0f4b..e3b2384 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.h
+++ b/graphics/composer/aidl/vts/ReadbackVts.h
@@ -172,10 +172,12 @@
 
     static Dataspace getDataspaceForColorMode(ColorMode mode);
 
-    static int32_t GetBytesPerPixel(PixelFormat pixelFormat);
+    static int32_t GetBitsPerChannel(PixelFormat pixelFormat);
+    static int32_t GetAlphaBits(PixelFormat pixelFormat);
 
-    static void fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData,
-                           PixelFormat pixelFormat, std::vector<Color> desiredPixelColors);
+    static void fillBuffer(uint32_t width, uint32_t height, uint32_t stride, int32_t bytesPerPixel,
+                           void* bufferData, PixelFormat pixelFormat,
+                           std::vector<Color> desiredPixelColors);
 
     static void clearColors(std::vector<Color>& expectedColors, int32_t width, int32_t height,
                             int32_t displayWidth);
@@ -189,11 +191,12 @@
     static const std::vector<Dataspace> dataspaces;
 
     static void compareColorBuffers(const std::vector<Color>& expectedColors, void* bufferData,
-                                    const uint32_t stride, const uint32_t width,
-                                    const uint32_t height, PixelFormat pixelFormat);
-    static void compareColorBuffers(void* expectedBuffer, void* actualBuffer, const uint32_t stride,
+                                    const uint32_t stride, int32_t bytesPerPixel,
                                     const uint32_t width, const uint32_t height,
                                     PixelFormat pixelFormat);
+    static void compareColorBuffers(void* expectedBuffer, void* actualBuffer, const uint32_t stride,
+                                    int32_t bytesPerPixel, const uint32_t width,
+                                    const uint32_t height, PixelFormat pixelFormat);
 };
 
 class ReadbackBuffer {
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.cpp b/graphics/composer/aidl/vts/RenderEngineVts.cpp
index bc5eb6f..8f8b5fd 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.cpp
+++ b/graphics/composer/aidl/vts/RenderEngineVts.cpp
@@ -81,7 +81,7 @@
     const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
                                     ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
                                     : mGraphicBuffer->getStride();
-    ReadbackHelper::compareColorBuffers(expectedColors, bufferData, stride,
+    ReadbackHelper::compareColorBuffers(expectedColors, bufferData, stride, bytesPerPixel,
                                         mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight(),
                                         mFormat);
     ASSERT_EQ(::android::OK, mGraphicBuffer->unlock());
@@ -108,7 +108,7 @@
 
     ASSERT_EQ(renderedStride, bufferStride);
 
-    ReadbackHelper::compareColorBuffers(renderedBufferData, bufferData, bufferStride,
+    ReadbackHelper::compareColorBuffers(renderedBufferData, bufferData, bufferStride, bytesPerPixel,
                                         mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight(),
                                         mFormat);
     ASSERT_EQ(::android::OK, buffer->unlock());
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 3d9253f..9db8794 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -496,11 +496,14 @@
             const auto& buffer = graphicBuffer->handle;
             void* clientBufData;
             const auto stride = static_cast<uint32_t>(graphicBuffer->stride);
-            graphicBuffer->lock(clientUsage, layer->getAccessRegion(), &clientBufData);
+            int bytesPerPixel = -1;
+            int bytesPerStride = -1;
+            graphicBuffer->lock(clientUsage, layer->getAccessRegion(), &clientBufData,
+                                &bytesPerPixel, &bytesPerStride);
 
-            ASSERT_NO_FATAL_FAILURE(
-                    ReadbackHelper::fillBuffer(layer->getWidth(), layer->getHeight(), stride,
-                                               clientBufData, clientFormat, expectedColors));
+            ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(
+                    layer->getWidth(), layer->getHeight(), stride, bytesPerPixel, clientBufData,
+                    clientFormat, expectedColors));
             int32_t clientFence;
             const auto unlockStatus = graphicBuffer->unlockAsync(&clientFence);
             ASSERT_EQ(::android::OK, unlockStatus);
@@ -677,15 +680,18 @@
         const auto& buffer = graphicBuffer->handle;
 
         void* clientBufData;
+        int bytesPerPixel = -1;
+        int bytesPerStride = -1;
         graphicBuffer->lock(clientUsage, {0, 0, getDisplayWidth(), getDisplayHeight()},
-                            &clientBufData);
+                            &clientBufData, &bytesPerPixel, &bytesPerStride);
 
         std::vector<Color> clientColors(
                 static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
         ReadbackHelper::fillColorsArea(clientColors, getDisplayWidth(), clientFrame, RED);
         ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(
                 static_cast<uint32_t>(getDisplayWidth()), static_cast<uint32_t>(getDisplayHeight()),
-                graphicBuffer->getStride(), clientBufData, clientFormat, clientColors));
+                graphicBuffer->getStride(), bytesPerPixel, clientBufData, clientFormat,
+                clientColors));
         int32_t clientFence;
         const auto unlockStatus = graphicBuffer->unlockAsync(&clientFence);
         ASSERT_EQ(::android::OK, unlockStatus);
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index ba15421..eaf23b5 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -1845,7 +1845,7 @@
         writer.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 0.5f, -1.f);
         execute();
         const auto errors = mReader.takeErrors();
-        EXPECT_EQ(1, errors.size());
+        ASSERT_EQ(1, errors.size());
         EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, errors[0].errorCode);
         GTEST_SUCCEED() << "SetDisplayBrightness is not supported";
         return;
diff --git a/graphics/mapper/4.0/utils/vts/Android.bp b/graphics/mapper/4.0/utils/vts/Android.bp
index c5f124c..1be460e 100644
--- a/graphics/mapper/4.0/utils/vts/Android.bp
+++ b/graphics/mapper/4.0/utils/vts/Android.bp
@@ -48,7 +48,7 @@
     ],
     export_static_lib_headers: [
         "android.hardware.graphics.allocator@4.0",
-        "android.hardware.graphics.common-V5-ndk",
+        "android.hardware.graphics.common-V6-ndk",
         "android.hardware.graphics.mapper@4.0",
     ],
     export_include_dirs: ["include"],
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index bae362f..f398c53 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -719,6 +719,38 @@
 }
 
 /**
+ * Test IMapper::lock and IMapper::unlock with no CPU usage requested.
+ */
+TEST_P(GraphicsMapperHidlTest, LockUnlockNoCPUUsage) {
+    const auto& info = mDummyDescriptorInfo;
+
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(
+            bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride));
+
+    // lock buffer with 0 usage
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+
+    hidl_handle acquireFenceHandle;
+
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+    mGralloc->getMapper()->lock(buffer, 0, region, acquireFenceHandle,
+                                [&](const auto& tmpError, const auto& /*tmpData*/) {
+                                    EXPECT_EQ(Error::BAD_VALUE, tmpError)
+                                            << "Locking with 0 access succeeded";
+                                });
+
+    mGralloc->getMapper()->unlock(buffer, [&](const auto& tmpError, const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+                << "Unlocking not locked buffer succeeded";
+    });
+
+    mGralloc->freeBuffer(bufferHandle);
+}
+
+/**
  *  Test multiple operations associated with different color formats
  */
 TEST_P(GraphicsMapperHidlTest, Lock_YCRCB_420_SP) {
diff --git a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
index 1e0c427..cfd3173 100644
--- a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
+++ b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
@@ -460,8 +460,8 @@
         ASSERT_NE(nullptr, outYCbCr->cr);
     }
 
-    YCbCr getAndroidYCbCr_P010(const native_handle_t* bufferHandle, uint8_t* data) {
-        YCbCr yCbCr_P010;
+    YCbCr getAndroidYCbCr_10bit(const native_handle_t* bufferHandle, uint8_t* data) {
+        YCbCr yCbCr_10bit;
         auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(bufferHandle);
         if (!decodeResult.has_value()) {
             ADD_FAILURE() << "failed to get plane layout";
@@ -472,12 +472,12 @@
         EXPECT_EQ(1, planeLayouts[0].components.size());
         EXPECT_EQ(2, planeLayouts[1].components.size());
 
-        yCbCr_P010.yCbCr.y = nullptr;
-        yCbCr_P010.yCbCr.cb = nullptr;
-        yCbCr_P010.yCbCr.cr = nullptr;
-        yCbCr_P010.yCbCr.ystride = 0;
-        yCbCr_P010.yCbCr.cstride = 0;
-        yCbCr_P010.yCbCr.chroma_step = 0;
+        yCbCr_10bit.yCbCr.y = nullptr;
+        yCbCr_10bit.yCbCr.cb = nullptr;
+        yCbCr_10bit.yCbCr.cr = nullptr;
+        yCbCr_10bit.yCbCr.ystride = 0;
+        yCbCr_10bit.yCbCr.cstride = 0;
+        yCbCr_10bit.yCbCr.chroma_step = 0;
         int64_t cb_offset = 0;
         int64_t cr_offset = 0;
 
@@ -493,15 +493,15 @@
                 auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
                 switch (type) {
                     case PlaneLayoutComponentType::Y:
-                        // For specs refer:
+                        // For specs refer to:
                         // https://docs.microsoft.com/en-us/windows/win32/medfound/10-bit-and-16-bit-yuv-video-formats
                         EXPECT_EQ(6, planeLayoutComponent.offsetInBits);
-                        EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.y);
+                        EXPECT_EQ(nullptr, yCbCr_10bit.yCbCr.y);
                         EXPECT_EQ(10, planeLayoutComponent.sizeInBits);
                         EXPECT_EQ(16, planeLayout.sampleIncrementInBits);
 
-                        yCbCr_P010.yCbCr.y = tmpData;
-                        yCbCr_P010.yCbCr.ystride = planeLayout.strideInBytes;
+                        yCbCr_10bit.yCbCr.y = tmpData;
+                        yCbCr_10bit.yCbCr.ystride = planeLayout.strideInBytes;
                         break;
 
                     case PlaneLayoutComponentType::CB:
@@ -509,46 +509,46 @@
                         sampleIncrementInBytes = bitsToBytes(planeLayout.sampleIncrementInBits);
                         EXPECT_EQ(4, sampleIncrementInBytes);
 
-                        if (yCbCr_P010.yCbCr.cstride == 0 && yCbCr_P010.yCbCr.chroma_step == 0) {
-                            yCbCr_P010.yCbCr.cstride = planeLayout.strideInBytes;
-                            yCbCr_P010.yCbCr.chroma_step = sampleIncrementInBytes;
+                        if (yCbCr_10bit.yCbCr.cstride == 0 && yCbCr_10bit.yCbCr.chroma_step == 0) {
+                            yCbCr_10bit.yCbCr.cstride = planeLayout.strideInBytes;
+                            yCbCr_10bit.yCbCr.chroma_step = sampleIncrementInBytes;
                         } else {
-                            EXPECT_EQ(yCbCr_P010.yCbCr.cstride, planeLayout.strideInBytes);
-                            EXPECT_EQ(yCbCr_P010.yCbCr.chroma_step, sampleIncrementInBytes);
+                            EXPECT_EQ(yCbCr_10bit.yCbCr.cstride, planeLayout.strideInBytes);
+                            EXPECT_EQ(yCbCr_10bit.yCbCr.chroma_step, sampleIncrementInBytes);
                         }
 
-                        if (yCbCr_P010.horizontalSubSampling == 0 &&
-                            yCbCr_P010.verticalSubSampling == 0) {
-                            yCbCr_P010.horizontalSubSampling = planeLayout.horizontalSubsampling;
-                            yCbCr_P010.verticalSubSampling = planeLayout.verticalSubsampling;
+                        if (yCbCr_10bit.horizontalSubSampling == 0 &&
+                            yCbCr_10bit.verticalSubSampling == 0) {
+                            yCbCr_10bit.horizontalSubSampling = planeLayout.horizontalSubsampling;
+                            yCbCr_10bit.verticalSubSampling = planeLayout.verticalSubsampling;
                         } else {
-                            EXPECT_EQ(yCbCr_P010.horizontalSubSampling,
+                            EXPECT_EQ(yCbCr_10bit.horizontalSubSampling,
                                       planeLayout.horizontalSubsampling);
-                            EXPECT_EQ(yCbCr_P010.verticalSubSampling,
+                            EXPECT_EQ(yCbCr_10bit.verticalSubSampling,
                                       planeLayout.verticalSubsampling);
                         }
 
                         if (type == PlaneLayoutComponentType::CB) {
-                            EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.cb);
-                            yCbCr_P010.yCbCr.cb = tmpData;
+                            EXPECT_EQ(nullptr, yCbCr_10bit.yCbCr.cb);
+                            yCbCr_10bit.yCbCr.cb = tmpData;
                             cb_offset = planeLayoutComponent.offsetInBits;
                         } else {
-                            EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.cr);
-                            yCbCr_P010.yCbCr.cr = tmpData;
+                            EXPECT_EQ(nullptr, yCbCr_10bit.yCbCr.cr);
+                            yCbCr_10bit.yCbCr.cr = tmpData;
                             cr_offset = planeLayoutComponent.offsetInBits;
                         }
                         break;
                     default:
                         break;
-                };
+                }
             }
         }
 
         EXPECT_EQ(cb_offset + bytesToBits(2), cr_offset);
-        EXPECT_NE(nullptr, yCbCr_P010.yCbCr.y);
-        EXPECT_NE(nullptr, yCbCr_P010.yCbCr.cb);
-        EXPECT_NE(nullptr, yCbCr_P010.yCbCr.cr);
-        return yCbCr_P010;
+        EXPECT_NE(nullptr, yCbCr_10bit.yCbCr.y);
+        EXPECT_NE(nullptr, yCbCr_10bit.yCbCr.cb);
+        EXPECT_NE(nullptr, yCbCr_10bit.yCbCr.cr);
+        return yCbCr_10bit;
     }
 };
 
@@ -750,6 +750,39 @@
 }
 
 /**
+ * Test IMapper::lock and IMapper::unlock with no CPU usage requested.
+ */
+TEST_P(GraphicsMapperStableCTests, LockUnlockNoCPUUsage) {
+    constexpr auto usage = BufferUsage::CPU_READ_RARELY | BufferUsage::CPU_WRITE_NEVER;
+    auto buffer = allocate({
+            .name = {"VTS_TEMP"},
+            .width = 64,
+            .height = 64,
+            .layerCount = 1,
+            .format = PixelFormat::RGBA_8888,
+            .usage = usage,
+            .reservedSize = 0,
+    });
+    ASSERT_NE(nullptr, buffer.get());
+
+    // lock buffer for writing
+    const auto& info = buffer->info();
+    const ARect region{0, 0, info.width, info.height};
+    auto handle = buffer->import();
+    uint8_t* data = nullptr;
+
+    EXPECT_EQ(AIMAPPER_ERROR_BAD_VALUE, mapper()->v5.lock(*handle, 0, region, -1, (void**)&data))
+            << "Locking with 0 access succeeded";
+
+    int releaseFence = -1;
+    EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(*handle, &releaseFence))
+            << "Unlocking not locked buffer succeeded";
+    if (releaseFence != -1) {
+        close(releaseFence);
+    }
+}
+
+/**
  *  Test multiple operations associated with different color formats
  */
 TEST_P(GraphicsMapperStableCTests, Lock_YCRCB_420_SP) {
@@ -1098,7 +1131,7 @@
                                                      region, -1, (void**)&data));
 
     YCbCr yCbCr;
-    ASSERT_NO_FATAL_FAILURE(yCbCr = getAndroidYCbCr_P010(*handle, data));
+    ASSERT_NO_FATAL_FAILURE(yCbCr = getAndroidYCbCr_10bit(*handle, data));
 
     constexpr uint32_t kCbCrSubSampleFactor = 2;
     ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.horizontalSubSampling);
@@ -1120,6 +1153,54 @@
     }
 }
 
+TEST_P(GraphicsMapperStableCTests, Lock_YCBCR_P210) {
+    BufferDescriptorInfo info{
+        .name = {"VTS_TEMP"},
+        .width = 64,
+        .height = 64,
+        .layerCount = 1,
+        .format = PixelFormat::YCBCR_P210,
+        .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+        .reservedSize = 0,
+    };
+    auto buffer = allocate(info);
+    if (!buffer) {
+        ASSERT_FALSE(isSupported(info));
+        GTEST_SUCCEED() << "YCBCR_P210 format is unsupported";
+        return;
+    }
+
+    // lock buffer for writing
+    const ARect region{0, 0, info.width, info.height};
+    auto handle = buffer->import();
+    uint8_t *data = nullptr;
+    ASSERT_EQ(AIMAPPER_ERROR_NONE,
+              mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage), region,
+                                -1, (void **)&data));
+
+    YCbCr yCbCr;
+    ASSERT_NO_FATAL_FAILURE(yCbCr = getAndroidYCbCr_10bit(*handle, data));
+
+    constexpr uint32_t kCbCrSubSampleFactor = 2;
+    ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.horizontalSubSampling);
+    ASSERT_EQ(1, yCbCr.verticalSubSampling);
+
+    ASSERT_EQ(0, info.height % 2);
+
+    // fill the data
+    fillYCbCrData(yCbCr.yCbCr, info.width, info.height,
+                  yCbCr.horizontalSubSampling, yCbCr.verticalSubSampling);
+    // verify the YCbCr data
+    verifyYCbCrData(yCbCr.yCbCr, info.width, info.height,
+                    yCbCr.horizontalSubSampling, yCbCr.verticalSubSampling);
+
+    int releaseFence = -1;
+    ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+    if (releaseFence != -1) {
+        close(releaseFence);
+    }
+}
+
 TEST_P(GraphicsMapperStableCTests, LockBadAccessRegion) {
     auto buffer = allocateGeneric();
     ASSERT_NE(nullptr, buffer);
diff --git a/health/2.0/vts/functional/Android.bp b/health/2.0/vts/functional/Android.bp
index 597fb50..206ec0f 100644
--- a/health/2.0/vts/functional/Android.bp
+++ b/health/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/health/2.1/default/Android.bp b/health/2.1/default/Android.bp
index b7bcea5..00d89e2 100644
--- a/health/2.1/default/Android.bp
+++ b/health/2.1/default/Android.bp
@@ -81,7 +81,7 @@
     ],
 
     vintf_fragments: [
-        "android.hardware.health@2.1.xml"
+        "android.hardware.health@2.1.xml",
     ],
 
     overrides: [
diff --git a/health/2.1/vts/functional/Android.bp b/health/2.1/vts/functional/Android.bp
index 238a150..ebb082d 100644
--- a/health/2.1/vts/functional/Android.bp
+++ b/health/2.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/health/aidl/default/LinkedCallback.h b/health/aidl/default/LinkedCallback.h
index 8c9c997..6b17be0 100644
--- a/health/aidl/default/LinkedCallback.h
+++ b/health/aidl/default/LinkedCallback.h
@@ -36,7 +36,7 @@
     // cookie when it's unlinked.
     static ::android::base::Result<LinkedCallback*> Make(
             std::shared_ptr<Health> service, std::shared_ptr<IHealthInfoCallback> callback);
-    // On callback died, unreigster it from the service.
+    // On callback died, unregister it from the service.
     void OnCallbackDied();
 
   private:
diff --git a/health/aidl/default/corpus/seed-2024-08-29-0 b/health/aidl/default/corpus/seed-2024-08-29-0
new file mode 100644
index 0000000..07fd0e9
--- /dev/null
+++ b/health/aidl/default/corpus/seed-2024-08-29-0
Binary files differ
diff --git a/health/aidl/default/corpus/seed-2024-08-29-1 b/health/aidl/default/corpus/seed-2024-08-29-1
new file mode 100644
index 0000000..ef19735
--- /dev/null
+++ b/health/aidl/default/corpus/seed-2024-08-29-1
Binary files differ
diff --git a/health/aidl/default/corpus/seed-2024-08-29-2 b/health/aidl/default/corpus/seed-2024-08-29-2
new file mode 100644
index 0000000..76addb7
--- /dev/null
+++ b/health/aidl/default/corpus/seed-2024-08-29-2
Binary files differ
diff --git a/health/aidl/vts/functional/Android.bp b/health/aidl/vts/functional/Android.bp
index 6d2b530..25ba5f8 100644
--- a/health/aidl/vts/functional/Android.bp
+++ b/health/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp
index ccf22ce..e78e044 100644
--- a/health/storage/1.0/vts/functional/Android.bp
+++ b/health/storage/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/health/storage/OWNERS b/health/storage/OWNERS
index 7af8d99..ec1fd8f 100644
--- a/health/storage/OWNERS
+++ b/health/storage/OWNERS
@@ -1,6 +1,9 @@
 # Bug component: 30545
 
+# Don't inherit owners from hardware/interfaces/health/
 set noparent
+# But inherit from hardware/interfaces
+include platform/hardware/interfaces:/OWNERS
 
 jaegeuk@google.com
 elsk@google.com
diff --git a/health/storage/aidl/Android.bp b/health/storage/aidl/Android.bp
index c614efb..44484d6 100644
--- a/health/storage/aidl/Android.bp
+++ b/health/storage/aidl/Android.bp
@@ -26,6 +26,7 @@
     vendor_available: true,
     srcs: ["android/hardware/health/storage/*.aidl"],
     stability: "vintf",
+    frozen: true,
     backend: {
         cpp: {
             enabled: false,
diff --git a/health/storage/aidl/vts/functional/Android.bp b/health/storage/aidl/vts/functional/Android.bp
index fe15170..083ec37 100644
--- a/health/storage/aidl/vts/functional/Android.bp
+++ b/health/storage/aidl/vts/functional/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/health/utils/libhealthloop/Android.bp b/health/utils/libhealthloop/Android.bp
index 7aaf905..08b3180 100644
--- a/health/utils/libhealthloop/Android.bp
+++ b/health/utils/libhealthloop/Android.bp
@@ -21,6 +21,23 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+bpf {
+    name: "filterPowerSupplyEvents.o_non_vendor",
+    srcs: ["filterPowerSupplyEvents.c"],
+    visibility: ["//visibility:private"],
+}
+
+bpf {
+    name: "filterPowerSupplyEvents.o",
+    srcs: ["filterPowerSupplyEvents.c"],
+    // "vendor: true" because all binaries that use this BPF filter are vendor
+    // binaries.
+    vendor: true,
+}
+
+// Since "required" sections are ignored in static library definitions,
+// filterPowerSupplyEvents.o has been added in
+// build/make/target/product/base_vendor.mk.
 cc_library_static {
     name: "libhealthloop",
     vendor_available: true,
@@ -30,10 +47,11 @@
         "utils.cpp",
     ],
     shared_libs: [
-        "libcutils",
         "libbase",
+        "libcutils",
     ],
     header_libs: [
+        "bpf_headers",
         "libbatteryservice_headers",
         "libhealthd_headers",
         "libutils_headers",
@@ -42,3 +60,32 @@
         "include",
     ],
 }
+
+cc_genrule {
+    name: "filterPowerSupplyEvents.h",
+    out: ["filterPowerSupplyEvents.h"],
+    srcs: [":filterPowerSupplyEvents.o_non_vendor"],
+    cmd: "cat $(in) | od -v -tx1 | cut -c9- | grep -v '^$$' | sed 's/^/0x/;s/ /, 0x/g;s/^, //;s/$$/,/' > $(out)",
+}
+
+cc_test_host {
+    name: "filterPowerSupplyEventsTest",
+    team: "trendy_team_pixel_system_sw_storage",
+    srcs: [
+        "filterPowerSupplyEventsTest.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbpf",
+    ],
+    static_libs: [
+        "libgmock",
+    ],
+    generated_headers: [
+        "libbpf_headers",
+    ],
+    device_first_generated_headers: [
+        "filterPowerSupplyEvents.h",
+    ],
+    compile_multilib: "64",
+}
diff --git a/health/utils/libhealthloop/HealthLoop.cpp b/health/utils/libhealthloop/HealthLoop.cpp
index 4190769..c5ad5a8 100644
--- a/health/utils/libhealthloop/HealthLoop.cpp
+++ b/health/utils/libhealthloop/HealthLoop.cpp
@@ -20,23 +20,22 @@
 #include <health/HealthLoop.h>
 
 #include <errno.h>
-#include <libgen.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/epoll.h>
+#include <sys/epoll.h>  // epoll_create1(), epoll_ctl(), epoll_wait()
 #include <sys/timerfd.h>
-#include <unistd.h>
+#include <unistd.h>  // read()
 
 #include <android-base/logging.h>
 #include <batteryservice/BatteryService.h>
-#include <cutils/klog.h>
+#include <cutils/klog.h>  // KLOG_*()
 #include <cutils/uevent.h>
 #include <healthd/healthd.h>
-#include <utils/Errors.h>
 
+#include <BpfSyscallWrappers.h>
 #include <health/utils.h>
 
+using android::base::ErrnoError;
+using android::base::Result;
+using android::base::unique_fd;
 using namespace android;
 using namespace std::chrono_literals;
 
@@ -44,6 +43,8 @@
 namespace hardware {
 namespace health {
 
+static constexpr uint32_t kUeventMsgLen = 2048;
+
 HealthLoop::HealthLoop() {
     InitHealthdConfig(&healthd_config_);
     awake_poll_interval_ = -1;
@@ -57,19 +58,18 @@
 int HealthLoop::RegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) {
     CHECK(!reject_event_register_);
 
-    auto* event_handler =
-            event_handlers_
-                    .emplace_back(std::make_unique<EventHandler>(EventHandler{this, fd, func}))
-                    .get();
+    auto* event_handler = event_handlers_
+                                  .emplace_back(std::make_unique<EventHandler>(
+                                          EventHandler{this, fd, std::move(func)}))
+                                  .get();
 
-    struct epoll_event ev;
-
-    ev.events = EPOLLIN;
+    struct epoll_event ev = {
+        .events = EPOLLIN | EPOLLERR,
+        .data.ptr = reinterpret_cast<void*>(event_handler),
+    };
 
     if (wakeup == EVENT_WAKEUP_FD) ev.events |= EPOLLWAKEUP;
 
-    ev.data.ptr = reinterpret_cast<void*>(event_handler);
-
     if (epoll_ctl(epollfd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
         KLOG_ERROR(LOG_TAG, "epoll_ctl failed; errno=%d\n", errno);
         return -1;
@@ -122,38 +122,65 @@
     ScheduleBatteryUpdate();
 }
 
-// TODO(b/140330870): Use BPF instead.
-#define UEVENT_MSG_LEN 2048
-void HealthLoop::UeventEvent(uint32_t /*epevents*/) {
-    // No need to lock because uevent_fd_ is guaranteed to be initialized.
-
-    char msg[UEVENT_MSG_LEN + 2];
-    char* cp;
-    int n;
-
-    n = uevent_kernel_multicast_recv(uevent_fd_, msg, UEVENT_MSG_LEN);
-    if (n <= 0) return;
-    if (n >= UEVENT_MSG_LEN) /* overflow -- discard */
-        return;
-
-    msg[n] = '\0';
-    msg[n + 1] = '\0';
-    cp = msg;
-
-    while (*cp) {
-        if (!strcmp(cp, "SUBSYSTEM=power_supply")) {
-            ScheduleBatteryUpdate();
-            break;
+// Returns true if and only if the battery statistics should be updated.
+bool HealthLoop::RecvUevents() {
+    bool update_stats = false;
+    for (;;) {
+        char msg[kUeventMsgLen + 2];
+        int n = uevent_kernel_multicast_recv(uevent_fd_, msg, kUeventMsgLen);
+        if (n < 0 && errno == ENOBUFS) {
+            update_stats = true;
+        }
+        if (n <= 0) return update_stats;
+        if (n >= kUeventMsgLen) {
+            // too long -- discard
+            continue;
+        }
+        if (update_stats) {
+            continue;
         }
 
-        /* advance to after the next \0 */
-        while (*cp++)
-            ;
+        msg[n] = '\0';
+        msg[n + 1] = '\0';
+        for (char* cp = msg; *cp;) {
+            if (strcmp(cp, "SUBSYSTEM=power_supply") == 0) {
+                update_stats = true;
+                break;
+            }
+
+            /* advance to after the next \0 */
+            while (*cp++) {
+            }
+        }
     }
 }
 
+void HealthLoop::UeventEvent(uint32_t /*epevents*/) {
+    if (RecvUevents()) {
+        ScheduleBatteryUpdate();
+    }
+}
+
+// Attach a BPF filter to the @uevent_fd file descriptor. This fails in recovery mode because BPF is
+// not supported in recovery mode. This fails for kernel versions 5.4 and before because the BPF
+// program is rejected by the BPF verifier of older kernels.
+Result<void> HealthLoop::AttachFilter(int uevent_fd) {
+    static const char prg[] =
+            "/sys/fs/bpf/vendor/prog_filterPowerSupplyEvents_skfilter_power_supply";
+    int filter_fd(bpf::retrieveProgram(prg));
+    if (filter_fd < 0) {
+        return ErrnoError() << "failed to load BPF program " << prg;
+    }
+    if (setsockopt(uevent_fd, SOL_SOCKET, SO_ATTACH_BPF, &filter_fd, sizeof(filter_fd)) < 0) {
+        close(filter_fd);
+        return ErrnoError() << "failed to attach BPF program";
+    }
+    close(filter_fd);
+    return {};
+}
+
 void HealthLoop::UeventInit(void) {
-    uevent_fd_.reset(uevent_open_socket(64 * 1024, true));
+    uevent_fd_.reset(uevent_create_socket(kUeventMsgLen, true));
 
     if (uevent_fd_ < 0) {
         KLOG_ERROR(LOG_TAG, "uevent_init: uevent_open_socket failed\n");
@@ -161,8 +188,25 @@
     }
 
     fcntl(uevent_fd_, F_SETFL, O_NONBLOCK);
+
+    Result<void> attach_result = AttachFilter(uevent_fd_);
+    if (!attach_result.ok()) {
+        std::string error_msg = attach_result.error().message();
+        error_msg +=
+                ". This is expected in recovery mode and also for kernel versions before 5.10.";
+        KLOG_WARNING(LOG_TAG, "%s\n", error_msg.c_str());
+    } else {
+        KLOG_INFO(LOG_TAG, "Successfully attached the BPF filter to the uevent socket\n");
+    }
+
     if (RegisterEvent(uevent_fd_, &HealthLoop::UeventEvent, EVENT_WAKEUP_FD))
         KLOG_ERROR(LOG_TAG, "register for uevent events failed\n");
+
+    if (uevent_bind(uevent_fd_.get()) < 0) {
+        uevent_fd_.reset();
+        KLOG_ERROR(LOG_TAG, "uevent_init: binding socket failed\n");
+        return;
+    }
 }
 
 void HealthLoop::WakeAlarmEvent(uint32_t /*epevents*/) {
diff --git a/health/utils/libhealthloop/filterPowerSupplyEvents.c b/health/utils/libhealthloop/filterPowerSupplyEvents.c
new file mode 100644
index 0000000..5296993
--- /dev/null
+++ b/health/utils/libhealthloop/filterPowerSupplyEvents.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2024 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 <bpf_helpers.h>    // load_word()
+#include <linux/bpf.h>      // struct __sk_buff
+#include <linux/netlink.h>  // struct nlmsghdr
+#include <stdint.h>         // uint32_t
+
+// M4: match 4 bytes. Returns 0 if all bytes match.
+static inline uint32_t M4(struct __sk_buff* skb, unsigned int offset, uint8_t c0, uint8_t c1,
+                          uint8_t c2, uint8_t c3) {
+    return load_word(skb, offset) ^ ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
+}
+
+// M2: match 2 bytes. Returns 0 if all bytes match.
+static inline uint16_t M2(struct __sk_buff* skb, unsigned int offset, uint8_t c0, uint8_t c1) {
+    return load_half(skb, offset) ^ ((c0 << 8) | c1);
+}
+
+// M1: match 1 byte. Returns 0 in case of a match.
+static inline uint8_t M1(struct __sk_buff* skb, unsigned int offset, uint8_t c0) {
+    return load_byte(skb, offset) ^ c0;
+}
+
+// Match "\0SUBSYSTEM=". Returns 0 in case of a match.
+#define MATCH_SUBSYSTEM_LENGTH 11
+static inline uint32_t match_subsystem(struct __sk_buff* skb, unsigned int offset) {
+    return M4(skb, offset + 0, '\0', 'S', 'U', 'B') | M4(skb, offset + 4, 'S', 'Y', 'S', 'T') |
+           M2(skb, offset + 8, 'E', 'M') | M1(skb, offset + 10, '=');
+}
+
+// Match "power_supply\0". Returns 0 in case of a match.
+#define MATCH_POWER_SUPPLY_LENGTH 13
+static inline uint32_t match_power_supply(struct __sk_buff* skb, unsigned int offset) {
+    return M4(skb, offset + 0, 'p', 'o', 'w', 'e') | M4(skb, offset + 4, 'r', '_', 's', 'u') |
+           M4(skb, offset + 8, 'p', 'p', 'l', 'y') | M1(skb, offset + 12, '\0');
+}
+
+// The Linux kernel 5.4 BPF verifier rejects this program, probably because of its size. Hence the
+// restriction that the kernel version must be at least 5.10.
+DEFINE_BPF_PROG_KVER("skfilter/power_supply", AID_ROOT, AID_SYSTEM, filterPowerSupplyEvents,
+                     KVER(5, 10, 0))
+(struct __sk_buff* skb) {
+    uint32_t i;
+
+    // The first character matched by match_subsystem() is a '\0'. Starting
+    // right past the netlink message header is fine since the SUBSYSTEM= text
+    // never occurs at the start. See also the kobject_uevent_env() implementation:
+    // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kobject_uevent.c?#n473
+    // The upper bound of this loop has been chosen not to exceed the maximum
+    // number of instructions in a BPF program (BPF loops are unrolled).
+    for (i = sizeof(struct nlmsghdr); i < 256; ++i) {
+        if (i + MATCH_SUBSYSTEM_LENGTH > skb->len) {
+            break;
+        }
+        if (match_subsystem(skb, i) == 0) {
+            goto found_subsystem;
+        }
+    }
+
+    // The SUBSYSTEM= text has not been found in the bytes that have been
+    // examined: let the user space software perform filtering.
+    return skb->len;
+
+found_subsystem:
+    i += MATCH_SUBSYSTEM_LENGTH;
+    if (i + MATCH_POWER_SUPPLY_LENGTH <= skb->len && match_power_supply(skb, i) == 0) {
+        return skb->len;
+    }
+    return 0;
+}
+
+LICENSE("Apache 2.0");
+CRITICAL("healthd");
diff --git a/health/utils/libhealthloop/filterPowerSupplyEventsTest.cpp b/health/utils/libhealthloop/filterPowerSupplyEventsTest.cpp
new file mode 100644
index 0000000..04b8bcd
--- /dev/null
+++ b/health/utils/libhealthloop/filterPowerSupplyEventsTest.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2024 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 <android-base/unique_fd.h>
+#include <bpf/libbpf.h>
+#include <gtest/gtest.h>
+#include <linux/bpf.h>  // SO_ATTACH_BPF
+#include <linux/netlink.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <string>
+#include <string_view>
+
+#define ASSERT_UNIX_OK(e) ASSERT_GE(e, 0) << strerror(errno)
+
+// TODO(bvanassche): remove the code below. See also b/357099095.
+#ifndef SO_ATTACH_BPF
+#define SO_ATTACH_BPF 50  // From <asm-generic/socket.h>.
+#endif
+
+using ::android::base::unique_fd;
+using ::testing::ScopedTrace;
+
+struct test_data {
+    bool discarded;
+    std::string_view str;
+};
+
+static const uint8_t binary_bpf_prog[] = {
+#include "filterPowerSupplyEvents.h"
+};
+
+static std::vector<std::unique_ptr<ScopedTrace>>* msg_vec;
+
+std::ostream& operator<<(std::ostream& os, const test_data& td) {
+    os << "{.discarded=" << td.discarded << ", .str=";
+    for (auto c : td.str) {
+        if (isprint(c)) {
+            os << c;
+        } else {
+            os << ".";
+        }
+    }
+    return os << '}';
+}
+
+#define RECORD_ERR_MSG(fmt, ...)                                          \
+    do {                                                                  \
+        char* str;                                                        \
+        if (asprintf(&str, fmt, ##__VA_ARGS__) < 0) break;                \
+        auto st = std::make_unique<ScopedTrace>(__FILE__, __LINE__, str); \
+        msg_vec->emplace_back(std::move(st));                             \
+        free(str);                                                        \
+    } while (0)
+
+int libbpf_print_fn(enum libbpf_print_level, const char* fmt, va_list args) {
+    char* str;
+    if (vasprintf(&str, fmt, args) < 0) {
+        return 0;
+    }
+    msg_vec->emplace_back(std::make_unique<ScopedTrace>(__FILE__, -1, str));
+    free(str);
+    return 0;
+}
+
+static void record_libbpf_output() {
+    libbpf_set_print(libbpf_print_fn);
+}
+
+class filterPseTest : public testing::TestWithParam<test_data> {};
+
+struct ConnectedSockets {
+    unique_fd write_fd;
+    unique_fd read_fd;
+};
+
+// socketpair() only supports AF_UNIX sockets. AF_UNIX sockets do not
+// support BPF filters. Hence connect two TCP sockets with each other.
+static ConnectedSockets ConnectSockets(int domain, int type, int protocol) {
+    int _server_fd = socket(domain, type, protocol);
+    if (_server_fd < 0) {
+        return {};
+    }
+    unique_fd server_fd(_server_fd);
+
+    int _write_fd = socket(domain, type, protocol);
+    if (_write_fd < 0) {
+        RECORD_ERR_MSG("socket: %s", strerror(errno));
+        return {};
+    }
+    unique_fd write_fd(_write_fd);
+
+    struct sockaddr_in sa = {.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY};
+    if (bind(_server_fd, (const struct sockaddr*)&sa, sizeof(sa)) < 0) {
+        RECORD_ERR_MSG("bind: %s", strerror(errno));
+        return {};
+    }
+    if (listen(_server_fd, 1) < 0) {
+        RECORD_ERR_MSG("listen: %s", strerror(errno));
+        return {};
+    }
+    socklen_t addr_len = sizeof(sa);
+    if (getsockname(_server_fd, (struct sockaddr*)&sa, &addr_len) < 0) {
+        RECORD_ERR_MSG("getsockname: %s", strerror(errno));
+        return {};
+    }
+    errno = 0;
+    if (connect(_write_fd, (const struct sockaddr*)&sa, sizeof(sa)) < 0 && errno != EINPROGRESS) {
+        RECORD_ERR_MSG("connect: %s", strerror(errno));
+        return {};
+    }
+    int _read_fd = accept(_server_fd, NULL, NULL);
+    if (_read_fd < 0) {
+        RECORD_ERR_MSG("accept: %s", strerror(errno));
+        return {};
+    }
+    unique_fd read_fd(_read_fd);
+
+    return {.write_fd = std::move(write_fd), .read_fd = std::move(read_fd)};
+}
+
+TEST_P(filterPseTest, filterPse) {
+    if (getuid() != 0) {
+        GTEST_SKIP() << "Must be run as root.";
+        return;
+    }
+    if (!msg_vec) {
+        msg_vec = new typeof(*msg_vec);
+    }
+    std::unique_ptr<int, void (*)(int*)> clear_msg_vec_at_end_of_scope(new int, [](int* p) {
+        msg_vec->clear();
+        delete p;
+    });
+    record_libbpf_output();
+
+    auto connected_sockets = ConnectSockets(AF_INET, SOCK_STREAM, 0);
+    unique_fd write_fd = std::move(connected_sockets.write_fd);
+    unique_fd read_fd = std::move(connected_sockets.read_fd);
+
+    ASSERT_UNIX_OK(fcntl(read_fd, F_SETFL, O_NONBLOCK));
+
+    bpf_object* obj = bpf_object__open_mem(binary_bpf_prog, sizeof(binary_bpf_prog), NULL);
+    ASSERT_TRUE(obj) << "bpf_object__open() failed" << strerror(errno);
+
+    // Find the BPF program within the object.
+    bpf_program* prog = bpf_object__find_program_by_name(obj, "filterPowerSupplyEvents");
+    ASSERT_TRUE(prog);
+
+    ASSERT_UNIX_OK(bpf_program__set_type(prog, BPF_PROG_TYPE_SOCKET_FILTER));
+
+    ASSERT_UNIX_OK(bpf_object__load(obj));
+
+    int filter_fd = bpf_program__fd(prog);
+    ASSERT_UNIX_OK(filter_fd);
+
+    int setsockopt_result =
+            setsockopt(read_fd, SOL_SOCKET, SO_ATTACH_BPF, &filter_fd, sizeof(filter_fd));
+    ASSERT_UNIX_OK(setsockopt_result);
+
+    const test_data param = GetParam();
+    const std::string header(sizeof(struct nlmsghdr), '\0');
+    ASSERT_EQ(header.length(), sizeof(struct nlmsghdr));
+    const std::string data = header + std::string(param.str);
+    const size_t len = data.length();
+    std::cerr.write(data.data(), data.length());
+    std::cerr << ")\n";
+    ASSERT_EQ(write(write_fd, data.data(), len), len);
+    std::array<uint8_t, 512> read_buf;
+    int bytes_read = read(read_fd, read_buf.data(), read_buf.size());
+    if (bytes_read < 0) {
+        ASSERT_EQ(errno, EAGAIN);
+        bytes_read = 0;
+    } else {
+        ASSERT_LT(bytes_read, read_buf.size());
+    }
+    EXPECT_EQ(bytes_read, param.discarded ? 0 : len);
+
+    bpf_object__close(obj);
+}
+
+static constexpr char input0[] = "a";
+static constexpr char input1[] = "abc\0SUBSYSTEM=block\0";
+static constexpr char input2[] = "\0SUBSYSTEM=block";
+static constexpr char input3[] = "\0SUBSYSTEM=power_supply";
+static constexpr char input4[] = "\0SUBSYSTEM=power_supply\0";
+static constexpr char input5[] =
+        "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
+        "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
+        "012345678901234567890123456789012345678901234567890123456789\0SUBSYSTEM=block\0";
+
+INSTANTIATE_TEST_SUITE_P(
+        filterPse, filterPseTest,
+        testing::Values(test_data{false, std::string_view(input0, sizeof(input0) - 1)},
+                        test_data{true, std::string_view(input1, sizeof(input1) - 1)},
+                        test_data{true, std::string_view(input2, sizeof(input2) - 1)},
+                        test_data{true, std::string_view(input3, sizeof(input3) - 1)},
+                        test_data{false, std::string_view(input4, sizeof(input4) - 1)},
+                        test_data{false, std::string_view(input5, sizeof(input5) - 1)}));
diff --git a/health/utils/libhealthloop/include/health/HealthLoop.h b/health/utils/libhealthloop/include/health/HealthLoop.h
index fc3066e..43c38dc 100644
--- a/health/utils/libhealthloop/include/health/HealthLoop.h
+++ b/health/utils/libhealthloop/include/health/HealthLoop.h
@@ -20,6 +20,7 @@
 #include <mutex>
 #include <vector>
 
+#include <android-base/result.h>
 #include <android-base/unique_fd.h>
 #include <healthd/healthd.h>
 
@@ -87,10 +88,12 @@
     };
 
     int InitInternal();
+    static android::base::Result<void> AttachFilter(int uevent_fd);
     void MainLoop();
     void WakeAlarmInit();
     void WakeAlarmEvent(uint32_t);
     void UeventInit();
+    bool RecvUevents();
     void UeventEvent(uint32_t);
     void WakeAlarmSetInterval(int interval);
     void PeriodicChores();
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index 8ff2382..1ce4f0c 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/input/common/aidl/Android.bp b/input/common/aidl/Android.bp
index 0759d2e..8721e5d 100644
--- a/input/common/aidl/Android.bp
+++ b/input/common/aidl/Android.bp
@@ -14,6 +14,7 @@
     vendor_available: true,
     srcs: ["android/hardware/input/common/*.aidl"],
     stability: "vintf",
+    frozen: true,
     backend: {
         cpp: {
             enabled: false,
diff --git a/input/processor/aidl/Android.bp b/input/processor/aidl/Android.bp
index 68adf32..6855b08 100644
--- a/input/processor/aidl/Android.bp
+++ b/input/processor/aidl/Android.bp
@@ -12,6 +12,7 @@
     name: "android.hardware.input.processor",
     host_supported: true,
     vendor_available: true,
+    frozen: true,
     srcs: ["android/hardware/input/processor/*.aidl"],
     imports: [
         "android.hardware.input.common-V1",
diff --git a/ir/1.0/vts/functional/Android.bp b/ir/1.0/vts/functional/Android.bp
index 983f2a4..7c23f03 100644
--- a/ir/1.0/vts/functional/Android.bp
+++ b/ir/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/ir/aidl/Android.bp b/ir/aidl/Android.bp
index 25f6c8f..c561c52 100644
--- a/ir/aidl/Android.bp
+++ b/ir/aidl/Android.bp
@@ -26,6 +26,7 @@
     vendor_available: true,
     srcs: ["android/hardware/ir/*.aidl"],
     stability: "vintf",
+    frozen: true,
     backend: {
         cpp: {
             enabled: false,
diff --git a/ir/aidl/vts/Android.bp b/ir/aidl/vts/Android.bp
index c2491b8..d42a7f4 100644
--- a/ir/aidl/vts/Android.bp
+++ b/ir/aidl/vts/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/keymaster/3.0/vts/functional/Android.bp b/keymaster/3.0/vts/functional/Android.bp
index fde32a7..4aa0692 100644
--- a/keymaster/3.0/vts/functional/Android.bp
+++ b/keymaster/3.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/keymaster/4.0/vts/functional/Android.bp b/keymaster/4.0/vts/functional/Android.bp
index e1dfcfc..cd12319 100644
--- a/keymaster/4.0/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/keymaster/4.0/vts/performance/Android.bp b/keymaster/4.0/vts/performance/Android.bp
index d7342ad..8f26871 100644
--- a/keymaster/4.0/vts/performance/Android.bp
+++ b/keymaster/4.0/vts/performance/Android.bp
@@ -33,6 +33,5 @@
         "android.hardware.keymaster@4.0",
         "libkeymaster4support",
         "libsoftkeymasterdevice",
-        "libchrome"
     ],
 }
diff --git a/keymaster/4.0/vts/performance/Benchmark.cpp b/keymaster/4.0/vts/performance/Benchmark.cpp
index e5fdff2..723b543 100644
--- a/keymaster/4.0/vts/performance/Benchmark.cpp
+++ b/keymaster/4.0/vts/performance/Benchmark.cpp
@@ -16,6 +16,8 @@
 
 #define LOG_TAG "keymaster_benchmark"
 
+#include <getopt.h>
+
 #include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
 #include <android/hardware/keymaster/4.0/types.h>
 #include <keymaster/keymaster_configuration.h>
@@ -36,8 +38,6 @@
 #include <benchmark/benchmark.h>
 #include <hidl/Status.h>
 
-#include <base/command_line.h>
-
 namespace android {
 namespace hardware {
 namespace keymaster {
@@ -700,14 +700,26 @@
 }  // namespace hardware
 }  // namespace android
 
+namespace {
+
+std::string ParseCommandLineFlags(int argc, char** argv) {
+    std::string service_name = "default";
+    static struct option long_options[] = {{"service_name", required_argument, 0, 's'},
+                                           {0, 0, 0, 0}};
+    int opt;
+    while ((opt = getopt_long(argc, argv, "s:", long_options, nullptr)) != -1) {
+        if (opt == 's') {
+            service_name = optarg;
+        }
+    }
+    return service_name;
+}
+
+}  // namespace
+
 int main(int argc, char** argv) {
     ::benchmark::Initialize(&argc, argv);
-    base::CommandLine::Init(argc, argv);
-    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-    auto service_name = command_line->GetSwitchValueASCII("service_name");
-    if (service_name.empty()) {
-        service_name = "default";
-    }
+    std::string service_name = ParseCommandLineFlags(argc, argv);
     android::hardware::keymaster::V4_0::test::keymaster =
             android::hardware::keymaster::V4_0::test::KeymasterWrapper::newInstance(service_name);
     if (!android::hardware::keymaster::V4_0::test::keymaster) {
diff --git a/keymaster/4.1/vts/functional/Android.bp b/keymaster/4.1/vts/functional/Android.bp
index 547ce38..04fc2d3 100644
--- a/keymaster/4.1/vts/functional/Android.bp
+++ b/keymaster/4.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
index 4a57f44..fc5979a 100644
--- a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -229,13 +229,13 @@
                                                          .Authorization(TAG_INCLUDE_UNIQUE_ID))));
 
     hidl_vec<hidl_vec<uint8_t>> cert_chain;
-    EXPECT_EQ(ErrorCode::UNIMPLEMENTED,
-              convert(AttestKey(
-                      AuthorizationSetBuilder()
+    ErrorCode result = convert(
+            AttestKey(AuthorizationSetBuilder()
                               .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
                               .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
                               .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
-                      &cert_chain)));
+                      &cert_chain));
+    EXPECT_TRUE(result == ErrorCode::UNIMPLEMENTED || result == ErrorCode::INVALID_ARGUMENT);
     CheckedDeleteKey();
 
     ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
@@ -244,13 +244,13 @@
                                                          .Digest(Digest::SHA_2_256)
                                                          .Authorization(TAG_INCLUDE_UNIQUE_ID))));
 
-    EXPECT_EQ(ErrorCode::UNIMPLEMENTED,
-              convert(AttestKey(
-                      AuthorizationSetBuilder()
+    result = convert(
+            AttestKey(AuthorizationSetBuilder()
                               .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
                               .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
                               .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
-                      &cert_chain)));
+                      &cert_chain));
+    EXPECT_TRUE(result == ErrorCode::UNIMPLEMENTED || result == ErrorCode::INVALID_ARGUMENT);
     CheckedDeleteKey();
 }
 
diff --git a/keymaster/aidl/Android.bp b/keymaster/aidl/Android.bp
index 0f2debd..c101f56 100644
--- a/keymaster/aidl/Android.bp
+++ b/keymaster/aidl/Android.bp
@@ -18,6 +18,16 @@
         java: {
             platform_apis: true,
         },
+        ndk: {
+            apex_available: [
+                "com.android.hardware.biometrics.face.virtual",
+                "com.android.hardware.biometrics.fingerprint.virtual",
+                "//apex_available:platform",
+            ],
+        },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
diff --git a/light/2.0/vts/functional/Android.bp b/light/2.0/vts/functional/Android.bp
index 91fb847..53e5446 100644
--- a/light/2.0/vts/functional/Android.bp
+++ b/light/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/light/aidl/Android.bp b/light/aidl/Android.bp
index c9fba95..142be6d 100644
--- a/light/aidl/Android.bp
+++ b/light/aidl/Android.bp
@@ -14,6 +14,7 @@
         "android/hardware/light/*.aidl",
     ],
     stability: "vintf",
+    frozen: true,
     backend: {
         java: {
             sdk_version: "module_current",
diff --git a/light/aidl/vts/functional/Android.bp b/light/aidl/vts/functional/Android.bp
index 16804ea..ba05e2b 100644
--- a/light/aidl/vts/functional/Android.bp
+++ b/light/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/macsec/aidl/default/MacsecPskPlugin.cpp b/macsec/aidl/default/MacsecPskPlugin.cpp
index 82d2545..8cb5283 100644
--- a/macsec/aidl/default/MacsecPskPlugin.cpp
+++ b/macsec/aidl/default/MacsecPskPlugin.cpp
@@ -18,7 +18,6 @@
 #include <openssl/cipher.h>
 #include <openssl/mem.h>
 
-#include <android-base/format.h>
 #include <android-base/logging.h>
 
 namespace aidl::android::hardware::macsec {
diff --git a/macsec/aidl/default/service.cpp b/macsec/aidl/default/service.cpp
index faf3a09..9d5d3bf 100644
--- a/macsec/aidl/default/service.cpp
+++ b/macsec/aidl/default/service.cpp
@@ -20,12 +20,11 @@
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
-namespace android::hardware::macsec {
-
 using namespace std::string_literals;
+using namespace android;
 using ::aidl::android::hardware::macsec::MacsecPskPlugin;
 
-extern "C" int main() {
+int main() {
     base::SetDefaultTag("MacsecPskPlugin");
     base::SetMinimumLogSeverity(base::VERBOSE);
 
@@ -40,4 +39,3 @@
     LOG(FATAL) << "MacsecPskPlugin exited unexpectedly!";
     return EXIT_FAILURE;
 }
-}  // namespace android::hardware::macsec
diff --git a/macsec/aidl/vts/functional/Android.bp b/macsec/aidl/vts/functional/Android.bp
index 0c8f43d..faf0d15 100644
--- a/macsec/aidl/vts/functional/Android.bp
+++ b/macsec/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_aaos_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/media/bufferpool/aidl/default/BufferPoolClient.cpp b/media/bufferpool/aidl/default/BufferPoolClient.cpp
index ce4ad8e..b61893f 100644
--- a/media/bufferpool/aidl/default/BufferPoolClient.cpp
+++ b/media/bufferpool/aidl/default/BufferPoolClient.cpp
@@ -748,6 +748,10 @@
     } else {
         connection = mRemoteConnection;
     }
+    if (!connection) {
+        ALOGE("connection null: fetchBufferHandle()");
+        return ResultStatus::CRITICAL_ERROR;
+    }
     std::vector<FetchInfo> infos;
     std::vector<FetchResult> results;
     infos.emplace_back(FetchInfo{ToAidl(transactionId), ToAidl(bufferId)});
diff --git a/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp b/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
index d80e651..2d34afe 100644
--- a/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
+++ b/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
@@ -93,9 +93,9 @@
 
 void validateAttributes(
         const std::map<const std::string, const testing::internal::RE>& knownPatterns,
-        const std::vector<const struct AttributePattern>& unknownPatterns,
+        const std::vector<struct AttributePattern>& unknownPatterns,
         hidl_vec<IOmxStore::Attribute> attributes) {
-    std::set<const std::string> attributeKeys;
+    std::set<std::string> attributeKeys;
     for (const auto& attr : attributes) {
         // Make sure there are no duplicates
         const auto [nodeIter, inserted] = attributeKeys.insert(attr.key);
@@ -179,7 +179,7 @@
          * tried for a match with the second element of the pair. If this second
          * match fails, the test will fail.
          */
-        const std::vector<const struct AttributePattern> unknownPatterns = {
+        const std::vector<struct AttributePattern> unknownPatterns = {
                 {"supports-[a-z0-9-]*", "0|1"}};
 
         validateAttributes(knownPatterns, unknownPatterns, attributes);
@@ -248,7 +248,7 @@
     };
 
     // Strings for matching rules for node attributes with key patterns
-    const std::vector<const struct AttributePattern> unknownPatterns = {
+    const std::vector<struct AttributePattern> unknownPatterns = {
             {"measured-frame-rate-" + size + "-range", range_num},
             {"feature-[a-zA-Z0-9_-]+", string},
     };
@@ -257,9 +257,9 @@
     const testing::internal::RE nodeNamePattern = "[a-zA-Z0-9._-]+";
     const testing::internal::RE nodeOwnerPattern = "[a-zA-Z0-9._-]+";
 
-    std::set<const std::string> roleKeys;
-    std::map<const std::string, std::set<const std::string>> nodeToRoles;
-    std::map<const std::string, std::set<const std::string>> ownerToNodes;
+    std::set<std::string> roleKeys;
+    std::map<const std::string, std::set<std::string>> nodeToRoles;
+    std::map<const std::string, std::set<std::string>> ownerToNodes;
     for (const IOmxStore::RoleInfo& role : roleList) {
         // Make sure there are no duplicates
         const auto [roleIter, inserted] = roleKeys.insert(role.role);
@@ -276,7 +276,7 @@
         }
 
         // Check the nodes for this role
-        std::set<const std::string> nodeKeys;
+        std::set<std::string> nodeKeys;
         for (const IOmxStore::NodeInfo& node : role.nodes) {
             // Make sure there are no duplicates
             const auto [nodeIter, inserted] = nodeKeys.insert(node.name);
@@ -317,7 +317,7 @@
 
         // Verify that roles for each node match with the information from
         // IOmxStore::listRoles().
-        std::set<const std::string> nodeKeys;
+        std::set<std::string> nodeKeys;
         for (IOmx::ComponentInfo node : nodeList) {
             // Make sure there are no duplicates
             const auto [nodeIter, inserted] = nodeKeys.insert(node.mName);
@@ -334,7 +334,7 @@
 
             // All the roles advertised by IOmxStore::listRoles() for this
             // node must be included in roleKeys.
-            std::set<const std::string> difference;
+            std::set<std::string> difference;
             std::set_difference(nodeToRoles[node.mName].begin(), nodeToRoles[node.mName].end(),
                                 roleKeys.begin(), roleKeys.end(),
                                 std::inserter(difference, difference.begin()));
@@ -347,7 +347,7 @@
         }
         // Check that all nodes obtained from IOmxStore::listRoles() are
         // supported by the their corresponding IOmx instances.
-        std::set<const std::string> difference;
+        std::set<std::string> difference;
         std::set_difference(nodes.begin(), nodes.end(), nodeKeys.begin(), nodeKeys.end(),
                             std::inserter(difference, difference.begin()));
         EXPECT_EQ(difference.empty(), true) << "IOmx::listNodes() for IOmx "
diff --git a/memtrack/1.0/vts/functional/Android.bp b/memtrack/1.0/vts/functional/Android.bp
index 852cd15..924fc27 100644
--- a/memtrack/1.0/vts/functional/Android.bp
+++ b/memtrack/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/memtrack/OWNERS b/memtrack/OWNERS
index a182ed9..8017da6 100644
--- a/memtrack/OWNERS
+++ b/memtrack/OWNERS
@@ -1,2 +1,3 @@
-# Bug component: 30545
-connoro@google.com
+# Bug component: 356484
+kaleshsingh@google.com
+surenb@google.com
diff --git a/memtrack/aidl/vts/Android.bp b/memtrack/aidl/vts/Android.bp
index f54388a..523c903 100644
--- a/memtrack/aidl/vts/Android.bp
+++ b/memtrack/aidl/vts/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 8048e62..ed0e72b 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 7c1c118..e65735f 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/neuralnetworks/1.2/utils/test/DeviceTest.cpp b/neuralnetworks/1.2/utils/test/DeviceTest.cpp
index 0e855c4..0d8c141 100644
--- a/neuralnetworks/1.2/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.2/utils/test/DeviceTest.cpp
@@ -54,10 +54,6 @@
         .execTime = std::numeric_limits<float>::max(),
         .powerUsage = std::numeric_limits<float>::max()};
 
-// FIXME: This function causes Clang to hang indefinitely when building with
-// -O1. Turn off optimization as a temporary workaround.
-// http://b/296850773
-#pragma clang optimize off
 template <typename... Args>
 auto makeCallbackReturn(Args&&... args) {
     return [argPack = std::make_tuple(std::forward<Args>(args)...)](const auto& cb) {
@@ -65,7 +61,6 @@
         return Void();
     };
 }
-#pragma clang optimize on
 
 sp<MockDevice> createMockDevice() {
     const auto mockDevice = MockDevice::create();
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 7e4b5bb..0a3c577 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index 07071cc..ab2d4a1 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_renderscript_nnapi",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/neuralnetworks/aidl/Android.bp b/neuralnetworks/aidl/Android.bp
index 145604c..e7583aa 100644
--- a/neuralnetworks/aidl/Android.bp
+++ b/neuralnetworks/aidl/Android.bp
@@ -11,13 +11,16 @@
     name: "android.hardware.neuralnetworks",
     host_supported: true,
     vendor_available: true,
+    frozen: true,
     srcs: [
         "android/hardware/neuralnetworks/*.aidl",
     ],
     stability: "vintf",
+    defaults: [
+        "android.hardware.graphics.common-latest",
+    ],
     imports: [
         "android.hardware.common-V2",
-        "android.hardware.graphics.common-V5",
     ],
     backend: {
         java: {
@@ -30,7 +33,6 @@
             apex_available: [
                 "//apex_available:platform",
                 "com.android.neuralnetworks",
-                "test_com.android.neuralnetworks",
             ],
             min_sdk_version: "30",
         },
@@ -40,28 +42,28 @@
             version: "1",
             imports: [
                 "android.hardware.common-V2",
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
             ],
         },
         {
             version: "2",
             imports: [
                 "android.hardware.common-V2",
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
             ],
         },
         {
             version: "3",
             imports: [
                 "android.hardware.common-V2",
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
             ],
         },
         {
             version: "4",
             imports: [
                 "android.hardware.common-V2",
-                "android.hardware.graphics.common-V5",
+                "android.hardware.graphics.common-V6",
             ],
         },
 
diff --git a/neuralnetworks/aidl/vts/functional/Android.bp b/neuralnetworks/aidl/vts/functional/Android.bp
index 04b4a45..20686c1 100644
--- a/neuralnetworks/aidl/vts/functional/Android.bp
+++ b/neuralnetworks/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp b/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
index 2fc9e65..6d4936b 100644
--- a/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
+++ b/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
@@ -108,7 +108,7 @@
     EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
     // Wait for OPEN_CPLT event
     auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.no_timeout);
     EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
     EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 
@@ -118,7 +118,7 @@
     EXPECT_EQ(data.size(), nfc_->write(data));
     // Wait for CORE_RESET_RSP
     res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.no_timeout);
     EXPECT_GE(6ul, res.args->last_data_.size());
     EXPECT_EQ((int)NfcStatus::OK, res.args->last_data_[3]);
     if (res.args->last_data_.size() == 6) {
@@ -127,7 +127,7 @@
         EXPECT_EQ(4ul, res.args->last_data_.size());
         nci_version = NCI_VERSION_2;
         res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-        EXPECT_TRUE(res.no_timeout);
+        ASSERT_TRUE(res.no_timeout);
     }
 
     /*
@@ -137,14 +137,14 @@
     EXPECT_EQ(NfcStatus::OK, nfc_->close());
     // Wait for CLOSE_CPLT event
     res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.no_timeout);
     EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
     EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 
     EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
     // Wait for OPEN_CPLT event
     res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.no_timeout);
     EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
     EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
   }
@@ -153,7 +153,7 @@
     EXPECT_EQ(NfcStatus::OK, nfc_->close());
     // Wait for CLOSE_CPLT event
     auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.no_timeout);
     EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
     EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
   }
@@ -186,7 +186,7 @@
   EXPECT_EQ(data.size(), nfc_->write(data));
   // Wait for CORE_RESET_RSP
   auto res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
 
   /* The response/notification format for CORE_RESET_CMD differs
    * with NCI 1.0 and 2.0. */
@@ -200,7 +200,7 @@
       EXPECT_EQ((int)NfcStatus::OK, res.args->last_data_[3]);
       // Wait for CORE_RESET_NTF
       res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-      EXPECT_TRUE(res.no_timeout);
+      ASSERT_TRUE(res.no_timeout);
       // Check if reset trigger was due to CORE_RESET_CMD
       EXPECT_LE(8ul, res.args->last_data_.size());
       EXPECT_EQ(2ul, res.args->last_data_[3]);
@@ -221,7 +221,7 @@
   EXPECT_EQ(data.size(), nfc_->write(data));
   // Wait for CORE_RESET_RSP
   auto res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
 
   /* The response/notification format for CORE_RESET_CMD differs
    * with NCI 1.0 and 2.0. */
@@ -235,7 +235,7 @@
       EXPECT_EQ((int)NfcStatus::OK, res.args->last_data_[3]);
       // Wait for CORE_RESET_NTF
       res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-      EXPECT_TRUE(res.no_timeout);
+      ASSERT_TRUE(res.no_timeout);
       // Check if reset trigger was due to CORE_RESET_CMD
       EXPECT_LE(8ul, res.args->last_data_.size());
       EXPECT_EQ(2ul, res.args->last_data_[3]);
@@ -257,7 +257,7 @@
   EXPECT_EQ(data.size(), nfc_->write(data));
   // Wait for RSP
   auto res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(4ul, res.args->last_data_.size());
   EXPECT_EQ(SYNTAX_ERROR, res.args->last_data_[3]);
 }
@@ -277,14 +277,14 @@
     EXPECT_EQ(data.size(), nfc_->write(data));
     // Wait for CORE_RESET_RSP
     auto res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.no_timeout);
     EXPECT_EQ((int)NfcStatus::OK, res.args->last_data_[3]);
 
     /* NCI 2.0 sends CORE_RESET_NTF everytime. */
     if (nci_version == NCI_VERSION_2) {
         // Wait for CORE_RESET_NTF
         res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-        EXPECT_TRUE(res.no_timeout);
+        ASSERT_TRUE(res.no_timeout);
         cmd = CORE_INIT_CMD_NCI20;
     } else {
         cmd = CORE_INIT_CMD;
@@ -294,7 +294,7 @@
     EXPECT_EQ(data.size(), nfc_->write(data));
     // Wait for CORE_INIT_RSP
     res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.no_timeout);
     EXPECT_EQ((int)NfcStatus::OK, res.args->last_data_[3]);
     // Send an Error Data Packet
     cmd = INVALID_COMMAND;
@@ -307,7 +307,7 @@
         EXPECT_EQ(data.size(), nfc_->write(data));
         // Wait for response with SYNTAX_ERROR
         res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-        EXPECT_TRUE(res.no_timeout);
+        ASSERT_TRUE(res.no_timeout);
         EXPECT_EQ(4ul, res.args->last_data_.size());
         EXPECT_EQ(SYNTAX_ERROR, res.args->last_data_[3]);
   }
@@ -317,7 +317,7 @@
   EXPECT_EQ(data.size(), nfc_->write(data));
   // Wait for CORE_CONN_CREATE_RSP
   res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(7ul, res.args->last_data_.size());
   EXPECT_EQ((int)NfcStatus::OK, res.args->last_data_[3]);
 }
@@ -335,14 +335,14 @@
     EXPECT_EQ(data.size(), nfc_->write(data));
     // Wait for CORE_RESET_RSP
     auto res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.no_timeout);
     EXPECT_EQ((int)NfcStatus::OK, res.args->last_data_[3]);
 
     /* NCI 2.0 sends CORE_RESET_NTF everytime. */
     if (nci_version == NCI_VERSION_2) {
         // Wait for CORE_RESET_NTF
         res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-        EXPECT_TRUE(res.no_timeout);
+        ASSERT_TRUE(res.no_timeout);
         cmd = CORE_INIT_CMD_NCI20;
     } else {
         cmd = CORE_INIT_CMD;
@@ -352,15 +352,15 @@
     EXPECT_EQ(data.size(), nfc_->write(data));
     // Wait for CORE_INIT_RSP
     res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.no_timeout);
     EXPECT_EQ((int)NfcStatus::OK, res.args->last_data_[3]);
     cmd = CORE_CONN_CREATE_CMD;
     data = cmd;
     EXPECT_EQ(data.size(), nfc_->write(data));
     // Wait for CORE_CONN_CREATE_RSP
     res = nfc_cb_->WaitForCallback(kCallbackNameSendData);
-    EXPECT_TRUE(res.no_timeout);
-    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.no_timeout);
     EXPECT_EQ(7ul, res.args->last_data_.size());
     EXPECT_EQ((int)NfcStatus::OK, res.args->last_data_[3]);
     uint8_t conn_id = res.args->last_data_[6];
@@ -414,7 +414,7 @@
   EXPECT_EQ(NfcStatus::OK, nfc_->powerCycle());
   // Wait for NfcEvent.OPEN_CPLT
   auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
   EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 }
@@ -428,7 +428,7 @@
   EXPECT_EQ(NfcStatus::OK, nfc_->close());
   // Wait for CLOSE_CPLT event
   auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
   EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 
@@ -437,7 +437,7 @@
   EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
   // Wait for OPEN_CPLT event
   res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
   EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 }
@@ -464,7 +464,7 @@
       EXPECT_EQ(NfcStatus::OK, status);
       // Wait for NfcEvent.POST_INIT_CPLT
       auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-      EXPECT_TRUE(res.no_timeout);
+      ASSERT_TRUE(res.no_timeout);
       EXPECT_EQ(NfcEvent::POST_INIT_CPLT, res.args->last_event_);
   }
 }
@@ -487,7 +487,7 @@
   EXPECT_EQ(NfcStatus::OK, nfc_->close());
   // Wait for CLOSE_CPLT event
   auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
   EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 
@@ -496,7 +496,7 @@
   EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
   // Wait for OPEN_CPLT event
   res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
   EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 }
@@ -518,7 +518,7 @@
   EXPECT_EQ(NfcStatus::OK, nfc_->close());
   // Wait for CLOSE_CPLT event
   auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
   EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 
@@ -527,7 +527,7 @@
   EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
   // Wait for OPEN_CPLT event
   res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
   EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 }
@@ -541,7 +541,7 @@
   EXPECT_EQ(NfcStatus::OK, nfc_->close());
   // Wait for CLOSE_CPLT event
   auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
   EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 
@@ -550,7 +550,7 @@
   EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
   // Wait for OPEN_CPLT event
   res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
   EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 }
@@ -564,14 +564,14 @@
   EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
   // Wait for OPEN_CPLT event
   auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
   EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 
   EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
   // Wait for OPEN_CPLT event
   res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
-  EXPECT_TRUE(res.no_timeout);
+  ASSERT_TRUE(res.no_timeout);
   EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
   EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
 }
diff --git a/nfc/aidl/Android.bp b/nfc/aidl/Android.bp
index ae68f17..1ffd274 100644
--- a/nfc/aidl/Android.bp
+++ b/nfc/aidl/Android.bp
@@ -27,13 +27,15 @@
     vendor_available: true,
     srcs: ["android/hardware/nfc/*.aidl"],
     stability: "vintf",
+    frozen: false,
     backend: {
         cpp: {
             enabled: false,
         },
         java: {
-            sdk_version: "module_current",
             enabled: false,
+            sdk_version: "module_current",
+            min_sdk_version: "35",
         },
         ndk: {
             enabled: true,
@@ -41,6 +43,7 @@
                 "//apex_available:platform",
                 "com.android.nfcservices",
             ],
+            min_sdk_version: "35",
         },
         rust: {
             enabled: true,
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl
index 7a0ae54..220912e 100644
--- a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl
@@ -44,4 +44,5 @@
   int write(in byte[] data);
   void setEnableVerboseLogging(in boolean enable);
   boolean isVerboseLoggingEnabled();
+  android.hardware.nfc.NfcStatus controlGranted();
 }
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl
index 92e0a9a..4fdfae8 100644
--- a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl
@@ -49,4 +49,6 @@
   byte[] offHostRouteUicc;
   byte[] offHostRouteEse;
   byte defaultIsoDepRoute;
+  byte[] offHostSimPipeIds = {};
+  boolean t4tNfceeEnable;
 }
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl
index dda258e..aebe836 100644
--- a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl
@@ -40,4 +40,6 @@
   PRE_DISCOVER_CPLT = 3,
   HCI_NETWORK_RESET = 4,
   ERROR = 5,
+  REQUEST_CONTROL = 6,
+  RELEASE_CONTROL = 7,
 }
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
index 021dfe2..2df0d35 100644
--- a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
@@ -43,4 +43,5 @@
   byte discoveryPollKovio;
   byte discoveryPollBPrime;
   byte discoveryListenBPrime;
+  byte protocolChineseId;
 }
diff --git a/nfc/aidl/android/hardware/nfc/INfc.aidl b/nfc/aidl/android/hardware/nfc/INfc.aidl
index 662f8d4..1d18b9e 100644
--- a/nfc/aidl/android/hardware/nfc/INfc.aidl
+++ b/nfc/aidl/android/hardware/nfc/INfc.aidl
@@ -140,4 +140,13 @@
      * @return true if verbose logging flag value is enabled, false if disabled.
      */
     boolean isVerboseLoggingEnabled();
+
+    /**
+     * Requests control of NFCC to libnfc-nci.
+     * If an API request is sent when the framework has no control of NFCC, the request will be
+     * queued until the control is released from HAL.
+     * The control will be taken out of the framework for at most 2 seconds.
+     * @return NfcStatus::OK on success and NfcStatus::FAILED on error.
+     */
+    NfcStatus controlGranted();
 }
diff --git a/nfc/aidl/android/hardware/nfc/NfcConfig.aidl b/nfc/aidl/android/hardware/nfc/NfcConfig.aidl
index 1b4fcfb..86eee8b 100644
--- a/nfc/aidl/android/hardware/nfc/NfcConfig.aidl
+++ b/nfc/aidl/android/hardware/nfc/NfcConfig.aidl
@@ -86,4 +86,12 @@
      * Default IsoDep route. 0x00 if there aren't any. Refer to NCI spec.
      */
     byte defaultIsoDepRoute;
+    /**
+     * Pipe IDs for UICC. Empty if not available
+     */
+    byte[] offHostSimPipeIds = {};
+    /**
+     * T4T NFCEE feature configuration
+     */
+    boolean t4tNfceeEnable;
 }
diff --git a/nfc/aidl/android/hardware/nfc/NfcEvent.aidl b/nfc/aidl/android/hardware/nfc/NfcEvent.aidl
index a78b1cd..7e0231a 100644
--- a/nfc/aidl/android/hardware/nfc/NfcEvent.aidl
+++ b/nfc/aidl/android/hardware/nfc/NfcEvent.aidl
@@ -50,4 +50,14 @@
      * Error event to notify upper layer when there's an unknown error.
      */
     ERROR = 5,
+    /**
+     * Request control event to notify upper layer when HAL
+     * request control of NFCC to libnfc-nci
+     */
+    REQUEST_CONTROL = 6,
+    /**
+     * Release control event to notify upper layer when HAL
+     * release control of NFCC to libnfc-nci.
+     */
+    RELEASE_CONTROL = 7,
 }
diff --git a/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl b/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
index f8e3228..021e307 100644
--- a/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
+++ b/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
@@ -33,4 +33,5 @@
     byte discoveryPollKovio;
     byte discoveryPollBPrime;
     byte discoveryListenBPrime;
+    byte protocolChineseId;
 }
diff --git a/nfc/aidl/vts/functional/Android.bp b/nfc/aidl/vts/functional/Android.bp
index d0b684b..8852f6c 100644
--- a/nfc/aidl/vts/functional/Android.bp
+++ b/nfc/aidl/vts/functional/Android.bp
@@ -38,7 +38,7 @@
         "libbinder_ndk",
     ],
     static_libs: [
-        "android.hardware.nfc-V1-ndk",
+        "android.hardware.nfc-V2-ndk",
     ],
     test_suites: [
         "general-tests",
@@ -49,6 +49,7 @@
 cc_test {
     name: "VtsNfcBehaviorChangesTest",
     defaults: [
+        "aconfig_lib_cc_shared_link.defaults",
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
@@ -57,21 +58,22 @@
         "CondVar.cpp",
     ],
     include_dirs: [
-        "system/nfc/src/gki/common",
-        "system/nfc/src/gki/ulinux",
-        "system/nfc/src/include",
-        "system/nfc/src/nfa/include",
-        "system/nfc/src/nfc/include",
-        "system/nfc/utils/include",
+        "packages/modules/Nfc/libnfc-nci/src/gki/common",
+        "packages/modules/Nfc/libnfc-nci/src/gki/ulinux",
+        "packages/modules/Nfc/libnfc-nci/src/include",
+        "packages/modules/Nfc/libnfc-nci/src/nfa/include",
+        "packages/modules/Nfc/libnfc-nci/src/nfc/include",
+        "packages/modules/Nfc/libnfc-nci/utils/include",
     ],
     shared_libs: [
+        "liblog",
         "libbinder",
         "libbinder_ndk",
         "libnativehelper",
         "libstatssocket",
     ],
     static_libs: [
-        "android.hardware.nfc-V1-ndk",
+        "android.hardware.nfc-V2-ndk",
         "android.hardware.nfc@1.0",
         "android.hardware.nfc@1.1",
         "android.hardware.nfc@1.2",
diff --git a/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp b/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp
index 977b25c..6e6ca3e 100644
--- a/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp
+++ b/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp
@@ -423,6 +423,11 @@
         EXPECT_GE((uint8_t)configValue.defaultIsoDepRoute, MIN_OFFHOST_ROUTE_ID);
         EXPECT_LE((uint8_t)configValue.defaultIsoDepRoute, MAX_OFFHOST_ROUTE_ID);
     }
+    for (auto simPipeId : configValue.offHostSimPipeIds) {
+        LOG(INFO) << StringPrintf("offHostSimPipeId= %x", simPipeId);
+        EXPECT_GE(simPipeId, MIN_OFFHOST_ROUTE_ID);
+        EXPECT_LE(simPipeId, MAX_OFFHOST_ROUTE_ID);
+    }
 }
 
 /*
@@ -440,6 +445,16 @@
     EXPECT_TRUE(!enabled);
 }
 
+TEST_P(NfcAidl, CheckControlGrantedStatus) {
+    int interface_version;
+    EXPECT_TRUE(infc_->getInterfaceVersion(&interface_version).isOk());
+    if (interface_version > 1) {
+        NfcStatus status;
+        EXPECT_TRUE(infc_->controlGranted(&status).isOk());
+        EXPECT_EQ(status, NfcStatus::OK);
+    }
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NfcAidl);
 INSTANTIATE_TEST_SUITE_P(Nfc, NfcAidl,
                          testing::ValuesIn(::android::getAidlHalInstanceNames(INfc::descriptor)),
diff --git a/oemlock/1.0/vts/functional/Android.bp b/oemlock/1.0/vts/functional/Android.bp
index f1b8d2f..80b4fdb 100644
--- a/oemlock/1.0/vts/functional/Android.bp
+++ b/oemlock/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_pixel_watch_system_software",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/oemlock/aidl/Android.bp b/oemlock/aidl/Android.bp
index 1c19bb1..f4533ed 100644
--- a/oemlock/aidl/Android.bp
+++ b/oemlock/aidl/Android.bp
@@ -10,6 +10,7 @@
 aidl_interface {
     name: "android.hardware.oemlock",
     vendor_available: true,
+    frozen: true,
     srcs: ["android/hardware/oemlock/*.aidl"],
     stability: "vintf",
     backend: {
diff --git a/oemlock/aidl/vts/Android.bp b/oemlock/aidl/vts/Android.bp
index eb999a9..e19bc6a 100644
--- a/oemlock/aidl/vts/Android.bp
+++ b/oemlock/aidl/vts/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_pixel_watch_system_software",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/power/1.0/vts/functional/Android.bp b/power/1.0/vts/functional/Android.bp
index 7d90a83..0bb1420 100644
--- a/power/1.0/vts/functional/Android.bp
+++ b/power/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_powermanager_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/power/1.1/vts/functional/Android.bp b/power/1.1/vts/functional/Android.bp
index 4270ab7..83f1e6d 100644
--- a/power/1.1/vts/functional/Android.bp
+++ b/power/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_powermanager_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/power/1.2/vts/functional/Android.bp b/power/1.2/vts/functional/Android.bp
index ab4b601..82184e8 100644
--- a/power/1.2/vts/functional/Android.bp
+++ b/power/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_powermanager_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/power/1.3/vts/functional/Android.bp b/power/1.3/vts/functional/Android.bp
index c1186e3..c164901 100644
--- a/power/1.3/vts/functional/Android.bp
+++ b/power/1.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_powermanager_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/power/OWNERS b/power/OWNERS
index 7229b22..13895bd 100644
--- a/power/OWNERS
+++ b/power/OWNERS
@@ -1,5 +1,3 @@
 # Bug component: 826709
-
-# ADPF virtual team
-lpy@google.com
+file:platform/frameworks/base:/ADPF_OWNERS
 wvw@google.com
diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp
index 4926b91..e934bc5 100644
--- a/power/aidl/default/Android.bp
+++ b/power/aidl/default/Android.bp
@@ -26,7 +26,7 @@
     defaults: ["android.hardware.power-ndk_shared"],
     relative_install_path: "hw",
     init_rc: [":android.hardware.power.rc"],
-    vintf_fragments: [":android.hardware.power.xml"],
+    vintf_fragments: ["power-default.xml"],
     vendor: true,
     shared_libs: [
         "android.hardware.common-V2-ndk",
diff --git a/power/aidl/vts/Android.bp b/power/aidl/vts/Android.bp
index c9285f4..e3e72d8 100644
--- a/power/aidl/vts/Android.bp
+++ b/power/aidl/vts/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_powermanager_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/power/stats/1.0/vts/functional/Android.bp b/power/stats/1.0/vts/functional/Android.bp
index 5a448d8..c11f848 100644
--- a/power/stats/1.0/vts/functional/Android.bp
+++ b/power/stats/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_powermanager_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/power/stats/aidl/default/Android.bp b/power/stats/aidl/default/Android.bp
index cc0fbf6..4c59d98 100644
--- a/power/stats/aidl/default/Android.bp
+++ b/power/stats/aidl/default/Android.bp
@@ -25,7 +25,7 @@
     name: "android.hardware.power.stats-service.example",
     relative_install_path: "hw",
     init_rc: [":android.hardware.power.stats.rc"],
-    vintf_fragments: [":android.hardware.power.stats.xml"],
+    vintf_fragments: ["power.stats-default.xml"],
     vendor: true,
     shared_libs: [
         "libbase",
diff --git a/power/stats/aidl/vts/Android.bp b/power/stats/aidl/vts/Android.bp
index b9a395b..4fdc184 100644
--- a/power/stats/aidl/vts/Android.bp
+++ b/power/stats/aidl/vts/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_powermanager_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/radio/1.0/Android.bp b/radio/1.0/Android.bp
index e49a50d..09cf9aa 100644
--- a/radio/1.0/Android.bp
+++ b/radio/1.0/Android.bp
@@ -25,7 +25,7 @@
     ],
     apex_available: [
         "//apex_available:platform",
-        "com.android.btservices",
+        "com.android.bt",
     ],
     gen_java: true,
 }
diff --git a/radio/1.0/vts/functional/Android.bp b/radio/1.0/vts/functional/Android.bp
index 2c0e70a..4ff5c2c 100644
--- a/radio/1.0/vts/functional/Android.bp
+++ b/radio/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/radio/1.1/vts/functional/Android.bp b/radio/1.1/vts/functional/Android.bp
index b3def8e..dc50cfb 100644
--- a/radio/1.1/vts/functional/Android.bp
+++ b/radio/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/radio/1.2/vts/functional/Android.bp b/radio/1.2/vts/functional/Android.bp
index a62000f..6bc0594 100644
--- a/radio/1.2/vts/functional/Android.bp
+++ b/radio/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/radio/1.3/vts/functional/Android.bp b/radio/1.3/vts/functional/Android.bp
index d96d391..9a0996b 100644
--- a/radio/1.3/vts/functional/Android.bp
+++ b/radio/1.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/radio/1.4/vts/functional/Android.bp b/radio/1.4/vts/functional/Android.bp
index 167dec8..de2ed2c 100644
--- a/radio/1.4/vts/functional/Android.bp
+++ b/radio/1.4/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/radio/1.5/vts/functional/Android.bp b/radio/1.5/vts/functional/Android.bp
index 4549d3c..83a2568 100644
--- a/radio/1.5/vts/functional/Android.bp
+++ b/radio/1.5/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/radio/1.6/vts/functional/Android.bp b/radio/1.6/vts/functional/Android.bp
index 2bc6af3..b78330e 100644
--- a/radio/1.6/vts/functional/Android.bp
+++ b/radio/1.6/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/radio/aidl/Android.bp b/radio/aidl/Android.bp
index f60c484..53ef145 100644
--- a/radio/aidl/Android.bp
+++ b/radio/aidl/Android.bp
@@ -14,6 +14,7 @@
     host_supported: true,
     srcs: ["android/hardware/radio/*.aidl"],
     stability: "vintf",
+    flags: ["-Werror"],
     backend: {
         cpp: {
             enabled: true,
@@ -37,7 +38,7 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
 
@@ -47,7 +48,8 @@
     host_supported: true,
     srcs: ["android/hardware/radio/config/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V3"],
+    imports: ["android.hardware.radio-V4"],
+    flags: ["-Werror"],
     backend: {
         cpp: {
             enabled: true,
@@ -71,7 +73,7 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
 
@@ -81,7 +83,8 @@
     host_supported: true,
     srcs: ["android/hardware/radio/data/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V3"],
+    imports: ["android.hardware.radio-V4"],
+    flags: ["-Werror"],
     backend: {
         cpp: {
             enabled: true,
@@ -105,7 +108,7 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 }
 
 aidl_interface {
@@ -114,7 +117,8 @@
     host_supported: true,
     srcs: ["android/hardware/radio/messaging/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V3"],
+    imports: ["android.hardware.radio-V4"],
+    flags: ["-Werror"],
     backend: {
         cpp: {
             enabled: true,
@@ -138,7 +142,7 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 }
 
 aidl_interface {
@@ -147,7 +151,8 @@
     host_supported: true,
     srcs: ["android/hardware/radio/modem/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V3"],
+    imports: ["android.hardware.radio-V4"],
+    flags: ["-Werror"],
     backend: {
         cpp: {
             enabled: true,
@@ -171,7 +176,7 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 }
 
 aidl_interface {
@@ -180,7 +185,8 @@
     host_supported: true,
     srcs: ["android/hardware/radio/network/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V3"],
+    imports: ["android.hardware.radio-V4"],
+    flags: ["-Werror"],
     backend: {
         cpp: {
             enabled: true,
@@ -204,7 +210,7 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 }
 
 aidl_interface {
@@ -213,6 +219,7 @@
     host_supported: true,
     srcs: ["android/hardware/radio/sap/*.aidl"],
     stability: "vintf",
+    flags: ["-Werror"],
     backend: {
         cpp: {
             enabled: true,
@@ -220,7 +227,7 @@
         java: {
             apex_available: [
                 "//apex_available:platform",
-                "com.android.btservices",
+                "com.android.bt",
             ],
             sdk_version: "module_current",
             min_sdk_version: "Tiramisu",
@@ -241,9 +248,10 @@
     host_supported: true,
     srcs: ["android/hardware/radio/sim/*.aidl"],
     stability: "vintf",
+    flags: ["-Werror"],
     imports: [
-        "android.hardware.radio-V3",
-        "android.hardware.radio.config-V3",
+        "android.hardware.radio-V4",
+        "android.hardware.radio.config-V4",
     ],
     backend: {
         cpp: {
@@ -277,7 +285,7 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 }
 
 aidl_interface {
@@ -286,7 +294,8 @@
     host_supported: true,
     srcs: ["android/hardware/radio/voice/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V3"],
+    imports: ["android.hardware.radio-V4"],
+    flags: ["-Werror"],
     backend: {
         cpp: {
             enabled: true,
@@ -310,7 +319,7 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 }
 
 aidl_interface {
@@ -319,9 +328,10 @@
     srcs: ["android/hardware/radio/ims/media/*.aidl"],
     stability: "vintf",
     imports: [
-        "android.hardware.radio-V3",
-        "android.hardware.radio.data-V3",
+        "android.hardware.radio-V4",
+        "android.hardware.radio.data-V4",
     ],
+    flags: ["-Werror"],
     backend: {
         cpp: {
             enabled: false,
@@ -347,7 +357,7 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 }
 
 aidl_interface {
@@ -355,7 +365,8 @@
     vendor_available: true,
     srcs: ["android/hardware/radio/ims/*.aidl"],
     stability: "vintf",
-    imports: ["android.hardware.radio-V3"],
+    imports: ["android.hardware.radio-V4"],
+    flags: ["-Werror"],
     backend: {
         cpp: {
             enabled: false,
@@ -375,5 +386,5 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl
index bc1c292..bba6bdd 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl
@@ -17,9 +17,10 @@
  * This interface is used by telephony and telecom to talk to cellular radio for the purpose of
  * radio configuration, and it is not associated with any specific modem or slot.
  * All the functions have minimum one parameter:
- * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
- * duration of a method call. If clients provide colliding serials (including passing the same
- * serial to different methods), multiple responses (one for each method call) must still be served.
+ * serial: which corresponds to the serial number of the request. Serial numbers must only be
+ * memorized for the duration of a method call. If clients provide colliding serials (including
+ * passing the same serial to different methods), multiple responses (one for each method call) must
+ * still be served.
  */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
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 782dbbf..27561b9 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
@@ -52,4 +52,6 @@
   BIP = (1 << 13) /* 8192 */,
   ENTERPRISE = (1 << 14) /* 16384 */,
   RCS = (1 << 15) /* 32768 */,
+  OEM_PAID = (1 << 16) /* 65536 */,
+  OEM_PRIVATE = (1 << 17) /* 131072 */,
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl
index 009b428..a0ca4bf 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.data;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum DataCallFailCause {
   NONE = 0,
   OPERATOR_BARRED = 0x08,
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 7f3fdc7..d68a9d7 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
@@ -37,9 +37,9 @@
 parcelable DataProfileInfo {
   int profileId;
   String apn;
-  android.hardware.radio.data.PdpProtocolType protocol;
-  android.hardware.radio.data.PdpProtocolType roamingProtocol;
-  android.hardware.radio.data.ApnAuthType authType;
+  android.hardware.radio.data.PdpProtocolType protocol = android.hardware.radio.data.PdpProtocolType.IP;
+  android.hardware.radio.data.PdpProtocolType roamingProtocol = android.hardware.radio.data.PdpProtocolType.IP;
+  android.hardware.radio.data.ApnAuthType authType = android.hardware.radio.data.ApnAuthType.NO_PAP_NO_CHAP;
   String user;
   String password;
   int type;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataThrottlingAction.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataThrottlingAction.aidl
index e1fedb8..f5fae50 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataThrottlingAction.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataThrottlingAction.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.data;
 /* @hide */
-@Backing(type="byte") @JavaDerive(toString=true) @VintfStability
+@Backing(type="byte") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum DataThrottlingAction {
   NO_DATA_THROTTLING,
   THROTTLE_SECONDARY_CARRIER,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/LinkAddress.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/LinkAddress.aidl
index bef4c73..67d679f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/LinkAddress.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/LinkAddress.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.data;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable LinkAddress {
   String address;
   int addressProperties;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PortRange.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PortRange.aidl
index 45e2dc9..e428f1a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PortRange.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PortRange.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.data;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable PortRange {
   int start;
   int end;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/RouteSelectionDescriptor.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/RouteSelectionDescriptor.aidl
index 8864c24..80c055e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/RouteSelectionDescriptor.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/RouteSelectionDescriptor.aidl
@@ -36,7 +36,7 @@
 @JavaDerive(toString=true) @VintfStability
 parcelable RouteSelectionDescriptor {
   byte precedence;
-  android.hardware.radio.data.PdpProtocolType sessionType;
+  android.hardware.radio.data.PdpProtocolType sessionType = android.hardware.radio.data.PdpProtocolType.IP;
   byte sscMode;
   android.hardware.radio.data.SliceInfo[] sliceInfo;
   String[] dnn;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SetupDataCallResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SetupDataCallResult.aidl
index 6ae626e..699cc4d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SetupDataCallResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SetupDataCallResult.aidl
@@ -33,13 +33,13 @@
 
 package android.hardware.radio.data;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable SetupDataCallResult {
-  android.hardware.radio.data.DataCallFailCause cause;
+  android.hardware.radio.data.DataCallFailCause cause = android.hardware.radio.data.DataCallFailCause.NONE;
   long suggestedRetryTime;
   int cid;
   int active;
-  android.hardware.radio.data.PdpProtocolType type;
+  android.hardware.radio.data.PdpProtocolType type = android.hardware.radio.data.PdpProtocolType.IP;
   String ifname;
   android.hardware.radio.data.LinkAddress[] addresses;
   String[] dnses;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrMode.aidl
index 36a538c..3b38e19 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrMode.aidl
@@ -33,8 +33,9 @@
 
 package android.hardware.radio.ims.media;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum AmrMode {
+  INVALID = 0,
   AMR_MODE_0 = (1 << 0) /* 1 */,
   AMR_MODE_1 = (1 << 1) /* 2 */,
   AMR_MODE_2 = (1 << 2) /* 4 */,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrParams.aidl
index dcf0dd1..eb65eb1 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrParams.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrParams.aidl
@@ -35,7 +35,7 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable AmrParams {
-  android.hardware.radio.ims.media.AmrMode amrMode;
+  android.hardware.radio.ims.media.AmrMode amrMode = android.hardware.radio.ims.media.AmrMode.INVALID;
   boolean octetAligned;
   int maxRedundancyMillis;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecParams.aidl
index 6eefb34..1c80f7a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecParams.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecParams.aidl
@@ -35,7 +35,7 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable CodecParams {
-  android.hardware.radio.ims.media.CodecType codecType;
+  android.hardware.radio.ims.media.CodecType codecType = android.hardware.radio.ims.media.CodecType.INVALID;
   byte rxPayloadTypeNumber;
   byte txPayloadTypeNumber;
   byte samplingRateKHz;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecType.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecType.aidl
index 98463b1..e97a647 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecType.aidl
@@ -35,6 +35,7 @@
 /* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum CodecType {
+  INVALID = 0,
   AMR = (1 << 0) /* 1 */,
   AMR_WB = (1 << 1) /* 2 */,
   EVS = (1 << 2) /* 4 */,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsMode.aidl
index 1a59389..ae0e1f7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsMode.aidl
@@ -33,8 +33,9 @@
 
 package android.hardware.radio.ims.media;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum EvsMode {
+  INVALID = 0,
   EVS_MODE_0 = (1 << 0) /* 1 */,
   EVS_MODE_1 = (1 << 1) /* 2 */,
   EVS_MODE_2 = (1 << 2) /* 4 */,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsParams.aidl
index deb53af..90d2204 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsParams.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsParams.aidl
@@ -35,8 +35,8 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable EvsParams {
-  android.hardware.radio.ims.media.EvsBandwidth bandwidth;
-  android.hardware.radio.ims.media.EvsMode evsMode;
+  android.hardware.radio.ims.media.EvsBandwidth bandwidth = android.hardware.radio.ims.media.EvsBandwidth.NONE;
+  android.hardware.radio.ims.media.EvsMode evsMode = android.hardware.radio.ims.media.EvsMode.INVALID;
   byte channelAwareMode;
   boolean useHeaderFullOnly;
   boolean useEvsModeSwitch;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
index 714442c..b9cc15c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.ims.media;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum RtcpXrReportBlockType {
   RTCPXR_NONE = 0,
   RTCPXR_LOSS_RLE_REPORT_BLOCK = (1 << 0) /* 1 */,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpConfig.aidl
index 472ec35..6af5523 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpConfig.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpConfig.aidl
@@ -36,7 +36,7 @@
 @JavaDerive(toString=true) @VintfStability
 parcelable RtpConfig {
   int direction;
-  android.hardware.radio.AccessNetwork accessNetwork;
+  android.hardware.radio.AccessNetwork accessNetwork = android.hardware.radio.AccessNetwork.UNKNOWN;
   android.hardware.radio.ims.media.RtpAddress remoteAddress;
   android.hardware.radio.ims.media.RtpSessionParams sessionParams;
   android.hardware.radio.ims.media.RtcpConfig rtcpConfig;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ConnectionFailureInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ConnectionFailureInfo.aidl
index 421f752..ae3bbac 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ConnectionFailureInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ConnectionFailureInfo.aidl
@@ -35,11 +35,12 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ConnectionFailureInfo {
-  android.hardware.radio.ims.ConnectionFailureInfo.ConnectionFailureReason failureReason;
+  android.hardware.radio.ims.ConnectionFailureInfo.ConnectionFailureReason failureReason = android.hardware.radio.ims.ConnectionFailureInfo.ConnectionFailureReason.INVALID;
   int causeCode;
   int waitTimeMillis;
-  @Backing(type="int") @VintfStability
+  @Backing(type="int") @SuppressWarnings(value={"redundant-name"}) @VintfStability
   enum ConnectionFailureReason {
+    INVALID = 0,
     REASON_ACCESS_DENIED = 1,
     REASON_NAS_FAILURE = 2,
     REASON_RACH_FAILURE = 3,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsCall.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsCall.aidl
index 3895d75..73d987a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsCall.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsCall.aidl
@@ -36,10 +36,10 @@
 @JavaDerive(toString=true) @VintfStability
 parcelable ImsCall {
   int index;
-  android.hardware.radio.ims.ImsCall.CallType callType;
-  android.hardware.radio.AccessNetwork accessNetwork;
-  android.hardware.radio.ims.ImsCall.CallState callState;
-  android.hardware.radio.ims.ImsCall.Direction direction;
+  android.hardware.radio.ims.ImsCall.CallType callType = android.hardware.radio.ims.ImsCall.CallType.NORMAL;
+  android.hardware.radio.AccessNetwork accessNetwork = android.hardware.radio.AccessNetwork.UNKNOWN;
+  android.hardware.radio.ims.ImsCall.CallState callState = android.hardware.radio.ims.ImsCall.CallState.ACTIVE;
+  android.hardware.radio.ims.ImsCall.Direction direction = android.hardware.radio.ims.ImsCall.Direction.INCOMING;
   boolean isHeldByRemote;
   @Backing(type="int")
   enum CallType {
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsDeregistrationReason.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsDeregistrationReason.aidl
index 5b5bd40..62dc69b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsDeregistrationReason.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsDeregistrationReason.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.ims;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum ImsDeregistrationReason {
   REASON_SIM_REMOVED = 1,
   REASON_SIM_REFRESH = 2,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistration.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistration.aidl
index 66d8165..73cfd07 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistration.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistration.aidl
@@ -33,11 +33,11 @@
 
 package android.hardware.radio.ims;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable ImsRegistration {
-  android.hardware.radio.ims.ImsRegistrationState regState;
-  android.hardware.radio.AccessNetwork accessNetworkType;
-  android.hardware.radio.ims.SuggestedAction suggestedAction;
+  android.hardware.radio.ims.ImsRegistrationState regState = android.hardware.radio.ims.ImsRegistrationState.NOT_REGISTERED;
+  android.hardware.radio.AccessNetwork accessNetworkType = android.hardware.radio.AccessNetwork.UNKNOWN;
+  android.hardware.radio.ims.SuggestedAction suggestedAction = android.hardware.radio.ims.SuggestedAction.NONE;
   int capabilities;
   const int IMS_MMTEL_CAPABILITY_NONE = 0;
   const int IMS_MMTEL_CAPABILITY_VOICE = (1 << 0) /* 1 */;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SrvccCall.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SrvccCall.aidl
index 21645da..a2e2ae5 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SrvccCall.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SrvccCall.aidl
@@ -36,10 +36,10 @@
 @JavaDerive(toString=true) @VintfStability
 parcelable SrvccCall {
   int index;
-  android.hardware.radio.ims.SrvccCall.CallType callType;
+  android.hardware.radio.ims.SrvccCall.CallType callType = android.hardware.radio.ims.SrvccCall.CallType.NORMAL;
   int callState;
-  android.hardware.radio.ims.SrvccCall.CallSubState callSubstate;
-  android.hardware.radio.ims.SrvccCall.ToneType ringbackToneType;
+  android.hardware.radio.ims.SrvccCall.CallSubState callSubstate = android.hardware.radio.ims.SrvccCall.CallSubState.NONE;
+  android.hardware.radio.ims.SrvccCall.ToneType ringbackToneType = android.hardware.radio.ims.SrvccCall.ToneType.NONE;
   boolean isMpty;
   boolean isMT;
   String number;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
index a0e3991..9982395 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.messaging;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable CdmaSmsSubaddress {
   int subaddressType;
   boolean odd;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl
index 40b9ddb..ff4a111 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl
@@ -35,7 +35,7 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ImsSmsMessage {
-  android.hardware.radio.RadioTechnologyFamily tech;
+  android.hardware.radio.RadioTechnologyFamily tech = android.hardware.radio.RadioTechnologyFamily.THREE_GPP;
   boolean retry;
   int messageRef;
   android.hardware.radio.messaging.CdmaSmsMessage[] cdmaMessage;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
index b44ab71..080a877 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
@@ -35,7 +35,7 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ActivityStatsTechSpecificInfo {
-  android.hardware.radio.AccessNetwork rat;
+  android.hardware.radio.AccessNetwork rat = android.hardware.radio.AccessNetwork.UNKNOWN;
   int frequencyRange;
   int[] txmModetimeMs;
   int rxModeTimeMs;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/DeviceStateType.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/DeviceStateType.aidl
index 1159f93..023658c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/DeviceStateType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/DeviceStateType.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.modem;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum DeviceStateType {
   POWER_SAVE_MODE,
   CHARGING_STATE,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigModem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigModem.aidl
index d453cb0..7d5537f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigModem.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigModem.aidl
@@ -36,7 +36,7 @@
 @JavaDerive(toString=true) @VintfStability
 parcelable HardwareConfigModem {
   int rilModel;
-  android.hardware.radio.RadioTechnology rat;
+  android.hardware.radio.RadioTechnology rat = android.hardware.radio.RadioTechnology.UNKNOWN;
   int maxVoiceCalls;
   int maxDataCalls;
   int maxStandby;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ImeiInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ImeiInfo.aidl
index a2df30d..96fb5a8 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ImeiInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ImeiInfo.aidl
@@ -35,11 +35,12 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable ImeiInfo {
-  android.hardware.radio.modem.ImeiInfo.ImeiType type;
+  android.hardware.radio.modem.ImeiInfo.ImeiType type = android.hardware.radio.modem.ImeiInfo.ImeiType.INVALID;
   String imei;
   String svn;
   @Backing(type="int") @VintfStability
   enum ImeiType {
+    INVALID = 0,
     PRIMARY = 1,
     SECONDARY = 2,
   }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl
index f97b9a2..bafcd19 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl
@@ -32,51 +32,175 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
-/**
- * @hide
- * @deprecated NV APIs are deprecated starting from Android U.
- */
+/* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum NvItem {
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
+  INVALID = 0,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_MEID = 1,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_MIN = 2,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_MDN = 3,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_ACCOLC = 4,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   DEVICE_MSL = 11,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   RTN_RECONDITIONED_STATUS = 12,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   RTN_ACTIVATION_DATE = 13,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   RTN_LIFE_TIMER = 14,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   RTN_LIFE_CALLS = 15,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   RTN_LIFE_DATA_TX = 16,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   RTN_LIFE_DATA_RX = 17,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   OMADM_HFA_LEVEL = 18,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   MIP_PROFILE_NAI = 31,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   MIP_PROFILE_HOME_ADDRESS = 32,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   MIP_PROFILE_AAA_AUTH = 33,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   MIP_PROFILE_HA_AUTH = 34,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   MIP_PROFILE_PRI_HA_ADDR = 35,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   MIP_PROFILE_SEC_HA_ADDR = 36,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   MIP_PROFILE_REV_TUN_PREF = 37,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   MIP_PROFILE_HA_SPI = 38,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   MIP_PROFILE_AAA_SPI = 39,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   MIP_PROFILE_MN_HA_SS = 40,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   MIP_PROFILE_MN_AAA_SS = 41,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_PRL_VERSION = 51,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_BC10 = 52,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_BC14 = 53,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_SO68 = 54,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_SO73_COP0 = 55,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_SO73_COP1TO7 = 56,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_1X_ADVANCED_ENABLED = 57,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_EHRPD_ENABLED = 58,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   CDMA_EHRPD_FORCED = 59,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   LTE_BAND_ENABLE_25 = 71,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   LTE_BAND_ENABLE_26 = 72,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   LTE_BAND_ENABLE_41 = 73,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   LTE_SCAN_PRIORITY_25 = 74,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   LTE_SCAN_PRIORITY_26 = 75,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   LTE_SCAN_PRIORITY_41 = 76,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   LTE_HIDDEN_BAND_PRIORITY_25 = 77,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   LTE_HIDDEN_BAND_PRIORITY_26 = 78,
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   LTE_HIDDEN_BAND_PRIORITY_41 = 79,
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl
index c38ceb7..c941246 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl
@@ -32,12 +32,15 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.radio.modem;
-/**
- * @hide
- * @deprecated NV APIs are deprecated starting from Android U.
- */
+/* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable NvWriteItem {
-  android.hardware.radio.modem.NvItem itemId;
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
+  android.hardware.radio.modem.NvItem itemId = android.hardware.radio.modem.NvItem.INVALID;
+  /**
+   * @deprecated NV APIs are deprecated starting from Android U.
+   */
   String value;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl
index b4208b7..e9937f0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.modem;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum ResetNvType {
   RELOAD,
   ERASE,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringInfo.aidl
index 67c9349..3c812c0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringInfo.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.network;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable BarringInfo {
   int serviceType;
   int barringType;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfo.aidl
index 6bb31b0..53d485a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfo.aidl
@@ -36,6 +36,6 @@
 @JavaDerive(toString=true) @VintfStability
 parcelable CellInfo {
   boolean registered;
-  android.hardware.radio.network.CellConnectionStatus connectionStatus;
+  android.hardware.radio.network.CellConnectionStatus connectionStatus = android.hardware.radio.network.CellConnectionStatus.NONE;
   android.hardware.radio.network.CellInfoRatSpecificInfo ratSpecificInfo;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellularIdentifierDisclosure.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellularIdentifierDisclosure.aidl
index cb542e8..540dc1e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellularIdentifierDisclosure.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellularIdentifierDisclosure.aidl
@@ -36,7 +36,7 @@
 @JavaDerive(toString=true) @VintfStability
 parcelable CellularIdentifierDisclosure {
   String plmn;
-  android.hardware.radio.network.CellularIdentifier identifier;
-  android.hardware.radio.network.NasProtocolMessage protocolMessage;
+  android.hardware.radio.network.CellularIdentifier identifier = android.hardware.radio.network.CellularIdentifier.UNKNOWN;
+  android.hardware.radio.network.NasProtocolMessage protocolMessage = android.hardware.radio.network.NasProtocolMessage.UNKNOWN;
   boolean isEmergency;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Domain.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Domain.aidl
index 0de7e20..81c286a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Domain.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Domain.aidl
@@ -35,6 +35,7 @@
 /* @hide */
 @Backing(type="int") @JavaDerive(toString=true) @VintfStability
 enum Domain {
+  INVALID = 0,
   CS = (1 << 0) /* 1 */,
   PS = (1 << 1) /* 2 */,
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyMode.aidl
index c5b067e..93c32fb 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyMode.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.network;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum EmergencyMode {
   EMERGENCY_WWAN = 1,
   EMERGENCY_WLAN = 2,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl
index 471c7a0..7273a94 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl
@@ -36,5 +36,5 @@
 @JavaDerive(toString=true) @VintfStability
 parcelable EmergencyNetworkScanTrigger {
   android.hardware.radio.AccessNetwork[] accessNetwork;
-  android.hardware.radio.network.EmergencyScanType scanType;
+  android.hardware.radio.network.EmergencyScanType scanType = android.hardware.radio.network.EmergencyScanType.NO_PREFERENCE;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl
index 3b8083d..47940f3 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl
@@ -35,9 +35,9 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable EmergencyRegResult {
-  android.hardware.radio.AccessNetwork accessNetwork;
-  android.hardware.radio.network.RegState regState;
-  android.hardware.radio.network.Domain emcDomain;
+  android.hardware.radio.AccessNetwork accessNetwork = android.hardware.radio.AccessNetwork.UNKNOWN;
+  android.hardware.radio.network.RegState regState = android.hardware.radio.network.RegState.NOT_REG_MT_NOT_SEARCHING_OP;
+  android.hardware.radio.network.Domain emcDomain = android.hardware.radio.network.Domain.INVALID;
   boolean isVopsSupported;
   boolean isEmcBearerSupported;
   byte nwProvidedEmc;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl
index bb34fe1..2ff454c 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl
@@ -37,7 +37,7 @@
 parcelable EutranRegistrationInfo {
   android.hardware.radio.network.LteVopsInfo lteVopsInfo;
   android.hardware.radio.network.NrIndicators nrIndicators;
-  android.hardware.radio.network.EutranRegistrationInfo.AttachResultType lteAttachResultType;
+  android.hardware.radio.network.EutranRegistrationInfo.AttachResultType lteAttachResultType = android.hardware.radio.network.EutranRegistrationInfo.AttachResultType.NONE;
   int extraInfo;
   const int EXTRA_CSFB_NOT_PREFERRED = (1 << 0) /* 1 */;
   const int EXTRA_SMS_ONLY = (1 << 1) /* 2 */;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanRequest.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanRequest.aidl
index 60eaf77..cdac0be 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanRequest.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanRequest.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.network;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable NetworkScanRequest {
   int type;
   int interval;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanResult.aidl
index 695a194..518a378 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanResult.aidl
@@ -33,10 +33,10 @@
 
 package android.hardware.radio.network;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable NetworkScanResult {
   int status;
-  android.hardware.radio.RadioError error;
+  android.hardware.radio.RadioError error = android.hardware.radio.RadioError.NONE;
   android.hardware.radio.network.CellInfo[] networkInfos;
   const int SCAN_STATUS_PARTIAL = 1;
   const int SCAN_STATUS_COMPLETE = 2;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrSignalStrength.aidl
index 11e7356..45e6ccf 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrSignalStrength.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrSignalStrength.aidl
@@ -43,5 +43,5 @@
   int csiSinr;
   int csiCqiTableIndex;
   byte[] csiCqiReport;
-  int timingAdvance = 0x7FFFFFFF;
+  int timingAdvance = android.hardware.radio.RadioConst.VALUE_UNAVAILABLE /* 2147483647 */;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl
index 61146aa..1b5b669 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.network;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable NrVopsInfo {
   byte vopsSupported;
   byte emcSupported;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfig.aidl
index 7d64f7e..f58e5ed 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfig.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfig.aidl
@@ -35,8 +35,8 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable PhysicalChannelConfig {
-  android.hardware.radio.network.CellConnectionStatus status;
-  android.hardware.radio.RadioTechnology rat;
+  android.hardware.radio.network.CellConnectionStatus status = android.hardware.radio.network.CellConnectionStatus.NONE;
+  android.hardware.radio.RadioTechnology rat = android.hardware.radio.RadioTechnology.UNKNOWN;
   int downlinkChannelNumber;
   int uplinkChannelNumber;
   int cellBandwidthDownlinkKhz;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifier.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifier.aidl
index 8229207..9a018f7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifier.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifier.aidl
@@ -35,7 +35,7 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable RadioAccessSpecifier {
-  android.hardware.radio.AccessNetwork accessNetwork;
+  android.hardware.radio.AccessNetwork accessNetwork = android.hardware.radio.AccessNetwork.UNKNOWN;
   android.hardware.radio.network.RadioAccessSpecifierBands bands;
   int[] channels;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioBandMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioBandMode.aidl
index 6058e30..cbf37b2 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioBandMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioBandMode.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.network;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum RadioBandMode {
   BAND_MODE_UNSPECIFIED,
   BAND_MODE_EURO,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl
index f11b911..5e40813 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.network;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum RegState {
   NOT_REG_MT_NOT_SEARCHING_OP = 0,
   REG_HOME = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl
index 625d970..814cde8 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl
@@ -35,9 +35,9 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable RegStateResult {
-  android.hardware.radio.network.RegState regState;
-  android.hardware.radio.RadioTechnology rat;
-  android.hardware.radio.network.RegistrationFailCause reasonForDenial;
+  android.hardware.radio.network.RegState regState = android.hardware.radio.network.RegState.NOT_REG_MT_NOT_SEARCHING_OP;
+  android.hardware.radio.RadioTechnology rat = android.hardware.radio.RadioTechnology.UNKNOWN;
+  android.hardware.radio.network.RegistrationFailCause reasonForDenial = android.hardware.radio.network.RegistrationFailCause.NONE;
   android.hardware.radio.network.CellIdentity cellIdentity;
   String registeredPlmn;
   android.hardware.radio.network.AccessTechnologySpecificInfo accessTechnologySpecificInfo;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SecurityAlgorithmUpdate.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SecurityAlgorithmUpdate.aidl
index 73ad180..8613f19 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SecurityAlgorithmUpdate.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SecurityAlgorithmUpdate.aidl
@@ -35,8 +35,8 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable SecurityAlgorithmUpdate {
-  android.hardware.radio.network.ConnectionEvent connectionEvent;
-  android.hardware.radio.network.SecurityAlgorithm encryption;
-  android.hardware.radio.network.SecurityAlgorithm integrity;
+  android.hardware.radio.network.ConnectionEvent connectionEvent = android.hardware.radio.network.ConnectionEvent.CS_SIGNALLING_GSM;
+  android.hardware.radio.network.SecurityAlgorithm encryption = android.hardware.radio.network.SecurityAlgorithm.A50;
+  android.hardware.radio.network.SecurityAlgorithm integrity = android.hardware.radio.network.SecurityAlgorithm.A50;
   boolean isUnprotectedEmergency;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalThresholdInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalThresholdInfo.aidl
index 77b4831..2041bad 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalThresholdInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalThresholdInfo.aidl
@@ -33,14 +33,14 @@
 
 package android.hardware.radio.network;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable SignalThresholdInfo {
   int signalMeasurement;
   int hysteresisMs;
   int hysteresisDb;
   int[] thresholds;
   boolean isEnabled;
-  android.hardware.radio.AccessNetwork ran;
+  android.hardware.radio.AccessNetwork ran = android.hardware.radio.AccessNetwork.UNKNOWN;
   const int SIGNAL_MEASUREMENT_TYPE_RSSI = 1;
   const int SIGNAL_MEASUREMENT_TYPE_RSCP = 2;
   const int SIGNAL_MEASUREMENT_TYPE_RSRP = 3;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/AppStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/AppStatus.aidl
index 898b616..a3e6d3a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/AppStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/AppStatus.aidl
@@ -33,16 +33,16 @@
 
 package android.hardware.radio.sim;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable AppStatus {
   int appType;
   int appState;
-  android.hardware.radio.sim.PersoSubstate persoSubstate;
+  android.hardware.radio.sim.PersoSubstate persoSubstate = android.hardware.radio.sim.PersoSubstate.UNKNOWN;
   String aidPtr;
   String appLabelPtr;
   boolean pin1Replaced;
-  android.hardware.radio.sim.PinState pin1;
-  android.hardware.radio.sim.PinState pin2;
+  android.hardware.radio.sim.PinState pin1 = android.hardware.radio.sim.PinState.UNKNOWN;
+  android.hardware.radio.sim.PinState pin2 = android.hardware.radio.sim.PinState.UNKNOWN;
   const int APP_STATE_UNKNOWN = 0;
   const int APP_STATE_DETECTED = 1;
   const int APP_STATE_PIN = 2;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardPowerState.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardPowerState.aidl
index 066777a..6a908c4 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardPowerState.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardPowerState.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.sim;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum CardPowerState {
   POWER_DOWN,
   POWER_UP,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl
index 1a9d621..0d7e48a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl
@@ -36,7 +36,7 @@
 @JavaDerive(toString=true) @VintfStability
 parcelable CardStatus {
   int cardState;
-  android.hardware.radio.sim.PinState universalPinState;
+  android.hardware.radio.sim.PinState universalPinState = android.hardware.radio.sim.PinState.UNKNOWN;
   int gsmUmtsSubscriptionAppIndex;
   int cdmaSubscriptionAppIndex;
   int imsSubscriptionAppIndex;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
index a5b8dc9..8f5672f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
@@ -44,7 +44,7 @@
    */
   android.hardware.radio.sim.Carrier[] excludedCarriers;
   boolean allowedCarriersPrioritized;
-  android.hardware.radio.sim.CarrierRestrictions.CarrierRestrictionStatus status;
+  android.hardware.radio.sim.CarrierRestrictions.CarrierRestrictionStatus status = android.hardware.radio.sim.CarrierRestrictions.CarrierRestrictionStatus.UNKNOWN;
   android.hardware.radio.sim.CarrierInfo[] allowedCarrierInfoList = {};
   android.hardware.radio.sim.CarrierInfo[] excludedCarrierInfoList = {};
   @Backing(type="int") @VintfStability
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PbReceivedStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PbReceivedStatus.aidl
index aaf9f3e..5070ff2 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PbReceivedStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PbReceivedStatus.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.sim;
 /* @hide */
-@Backing(type="byte") @JavaDerive(toString=true) @VintfStability
+@Backing(type="byte") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum PbReceivedStatus {
   PB_RECEIVED_OK = 1,
   PB_RECEIVED_ERROR = 2,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
index 8cfe417..75b8f6b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.sim;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum SimLockMultiSimPolicy {
   NO_MULTISIM_POLICY,
   ONE_VALID_SIM_MUST_BE_PRESENT,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimRefreshResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimRefreshResult.aidl
index 81ba510..c546565 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimRefreshResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimRefreshResult.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.sim;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable SimRefreshResult {
   int type;
   int efId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl
index b45a45b..27130b4 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl
@@ -48,7 +48,7 @@
   String name;
   int namePresentation;
   android.hardware.radio.voice.UusInfo[] uusInfo;
-  android.hardware.radio.voice.AudioQuality audioQuality;
+  android.hardware.radio.voice.AudioQuality audioQuality = android.hardware.radio.voice.AudioQuality.UNSPECIFIED;
   String forwardedNumber;
   const int PRESENTATION_ALLOWED = 0;
   const int PRESENTATION_RESTRICTED = 1;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
index 300b03f..0142792 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.voice;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable CdmaDisplayInfoRecord {
   String alphaBuf;
   const int CDMA_ALPHA_INFO_BUFFER_LENGTH = 64;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl
index 2f7f5f0..c71a8be 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.voice;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable CdmaInformationRecord {
   int name;
   android.hardware.radio.voice.CdmaDisplayInfoRecord[] display;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
index c3b0d5a..974e795 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.voice;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable CdmaNumberInfoRecord {
   String number;
   byte numberType;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
index 93c7c6b..818d107 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.voice;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable CdmaRedirectingNumberInfoRecord {
   android.hardware.radio.voice.CdmaNumberInfoRecord redirectingNumber;
   int redirectingReason;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/ClipStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/ClipStatus.aidl
index c38c801..3153e0a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/ClipStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/ClipStatus.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.voice;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum ClipStatus {
   CLIP_PROVISIONED,
   CLIP_UNPROVISIONED,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyCallRouting.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyCallRouting.aidl
index 3099a20..a45f388 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyCallRouting.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyCallRouting.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.voice;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum EmergencyCallRouting {
   UNKNOWN,
   EMERGENCY,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl
index 0cac135..17a039f 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl
@@ -33,8 +33,9 @@
 
 package android.hardware.radio.voice;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum LastCallFailCause {
+  INVALID = 0,
   UNOBTAINABLE_NUMBER = 1,
   NO_ROUTE_TO_DESTINATION = 3,
   CHANNEL_UNACCEPTABLE = 6,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCauseInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
index 151adf2..c36a934 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
@@ -35,6 +35,6 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable LastCallFailCauseInfo {
-  android.hardware.radio.voice.LastCallFailCause causeCode;
+  android.hardware.radio.voice.LastCallFailCause causeCode = android.hardware.radio.voice.LastCallFailCause.INVALID;
   String vendorCause;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SsInfoData.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SsInfoData.aidl
index 24365dc..2af38fe 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SsInfoData.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SsInfoData.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.voice;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable SsInfoData {
   int[] ssInfo;
   const int SS_INFO_MAX = 4;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/StkCcUnsolSsResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
index 999f47c..d265374 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
@@ -39,7 +39,7 @@
   int requestType;
   int teleserviceType;
   int serviceClass;
-  android.hardware.radio.RadioError result;
+  android.hardware.radio.RadioError result = android.hardware.radio.RadioError.NONE;
   android.hardware.radio.voice.SsInfoData[] ssInfo;
   android.hardware.radio.voice.CfData[] cfData;
   const int REQUEST_TYPE_ACTIVATION = 0;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UusInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UusInfo.aidl
index 3c84c8d..79c77ee 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UusInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UusInfo.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio.voice;
 /* @hide */
-@JavaDerive(toString=true) @VintfStability
+@JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 parcelable UusInfo {
   int uusType;
   int uusDcs;
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioConst.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioConst.aidl
index 970cd1e..e24a35d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioConst.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioConst.aidl
@@ -35,6 +35,9 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable RadioConst {
+  const int VALUE_UNAVAILABLE = 0x7FFFFFFF;
+  const long VALUE_UNAVAILABLE_LONG = 0x7FFFFFFFFFFFFFFF;
+  const byte VALUE_UNAVAILABLE_BYTE = 0xFFu8;
   const int MAX_RILDS = 3;
   const int MAX_UUID_LENGTH = 64;
   const int CARD_MAX_APPS = 8;
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioError.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioError.aidl
index 02c5370..e782e73 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioError.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioError.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.radio;
 /* @hide */
-@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+@Backing(type="int") @JavaDerive(toString=true) @SuppressWarnings(value={"redundant-name"}) @VintfStability
 enum RadioError {
   NONE = 0,
   RADIO_NOT_AVAILABLE = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfo.aidl
index f03a73b..bfab0c5 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfo.aidl
@@ -35,7 +35,7 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable RadioResponseInfo {
-  android.hardware.radio.RadioResponseType type;
+  android.hardware.radio.RadioResponseType type = android.hardware.radio.RadioResponseType.SOLICITED;
   int serial;
-  android.hardware.radio.RadioError error;
+  android.hardware.radio.RadioError error = android.hardware.radio.RadioError.NONE;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfoModem.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfoModem.aidl
index 2e0c315..c445fec 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfoModem.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfoModem.aidl
@@ -35,8 +35,8 @@
 /* @hide */
 @JavaDerive(toString=true) @VintfStability
 parcelable RadioResponseInfoModem {
-  android.hardware.radio.RadioResponseType type;
+  android.hardware.radio.RadioResponseType type = android.hardware.radio.RadioResponseType.SOLICITED;
   int serial;
-  android.hardware.radio.RadioError error;
+  android.hardware.radio.RadioError error = android.hardware.radio.RadioError.NONE;
   boolean isEnabled;
 }
diff --git a/radio/aidl/android/hardware/radio/RadioConst.aidl b/radio/aidl/android/hardware/radio/RadioConst.aidl
index 7b923b9..df27526 100644
--- a/radio/aidl/android/hardware/radio/RadioConst.aidl
+++ b/radio/aidl/android/hardware/radio/RadioConst.aidl
@@ -20,6 +20,9 @@
 @VintfStability
 @JavaDerive(toString=true)
 parcelable RadioConst {
+    const int VALUE_UNAVAILABLE = 0x7FFFFFFF;
+    const long VALUE_UNAVAILABLE_LONG = 0x7FFFFFFFFFFFFFFF;
+    const byte VALUE_UNAVAILABLE_BYTE = 0xFFu8;
     const int MAX_RILDS = 3;
     const int MAX_UUID_LENGTH = 64;
     const int CARD_MAX_APPS = 8;
diff --git a/radio/aidl/android/hardware/radio/RadioError.aidl b/radio/aidl/android/hardware/radio/RadioError.aidl
index 9c39bc4..6ce8f67 100644
--- a/radio/aidl/android/hardware/radio/RadioError.aidl
+++ b/radio/aidl/android/hardware/radio/RadioError.aidl
@@ -20,6 +20,7 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum RadioError {
     /**
      * Success
diff --git a/radio/aidl/android/hardware/radio/RadioResponseInfo.aidl b/radio/aidl/android/hardware/radio/RadioResponseInfo.aidl
index 25195aa..926ccf6 100644
--- a/radio/aidl/android/hardware/radio/RadioResponseInfo.aidl
+++ b/radio/aidl/android/hardware/radio/RadioResponseInfo.aidl
@@ -26,7 +26,7 @@
     /**
      * Response type
      */
-    RadioResponseType type;
+    RadioResponseType type = RadioResponseType.SOLICITED;
     /**
      * Serial number of the request
      */
@@ -34,5 +34,5 @@
     /**
      * Response error
      */
-    RadioError error;
+    RadioError error = RadioError.NONE;
 }
diff --git a/radio/aidl/android/hardware/radio/RadioResponseInfoModem.aidl b/radio/aidl/android/hardware/radio/RadioResponseInfoModem.aidl
index 286f397..3e76a93 100644
--- a/radio/aidl/android/hardware/radio/RadioResponseInfoModem.aidl
+++ b/radio/aidl/android/hardware/radio/RadioResponseInfoModem.aidl
@@ -26,7 +26,7 @@
     /**
      * Response type
      */
-    RadioResponseType type;
+    RadioResponseType type = RadioResponseType.SOLICITED;
     /**
      * Serial number of the request
      */
@@ -34,7 +34,7 @@
     /**
      * Response error
      */
-    RadioError error;
+    RadioError error = RadioError.NONE;
     /**
      * Whether the modem is enabled or not
      */
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
index 8f4dff4..936315c 100644
--- a/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
@@ -17,9 +17,10 @@
  * This interface is used by telephony and telecom to talk to cellular radio for the purpose of
  * radio configuration, and it is not associated with any specific modem or slot.
  * All the functions have minimum one parameter:
- * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
- * duration of a method call. If clients provide colliding serials (including passing the same
- * serial to different methods), multiple responses (one for each method call) must still be served.
+ * serial: which corresponds to the serial number of the request. Serial numbers must only be
+ * memorized for the duration of a method call. If clients provide colliding serials (including
+ * passing the same serial to different methods), multiple responses (one for each method call) must
+ * still be served.
  */
 
 package android.hardware.radio.config;
@@ -108,12 +109,12 @@
 
     /**
      * Set preferred data modem Id.
-     * In a multi-SIM device, notify modem layer which logical modem will be used primarily
-     * for data. It helps modem with resource optimization and decisions of what data connections
-     * should be satisfied.
+     * In a multi-SIM device, notify the modem layer which logical modem will be used primarily
+     * for data. It helps the modem with resource optimization and decisions of what data
+     * connections should be satisfied.
      *
      * @param serial Serial number of request.
-     * @param modem Id the logical modem ID, which should match one of modem IDs returned
+     * @param modemId the logical modem ID which should match one of the modem IDs returned
      * from getPhoneCapability().
      *
      * Response callback is IRadioConfigResponse.setPreferredDataModemResponse()
@@ -136,30 +137,30 @@
     /**
      * Set SIM Slot mapping.
      *
-     * Maps the logical slots to the SlotPortMapping which consist of both physical slot id and port
-     * id. Logical slot is the slot that is seen by modem. Physical slot is the actual physical
-     * slot. PortId is the id (enumerated value) for the associated port available on the SIM. Each
-     * physical slot can have multiple ports which enables multi-enabled profile(MEP). If eUICC
-     * physical slot supports 2 ports, then the portId is numbered 0,1 and if eUICC2 supports 4
-     * ports then the portID is numbered 0,1,2,3. Each portId is unique within a UICC physical slot
-     * but not necessarily unique across UICC’s. SEP(Single enabled profile) eUICC and non-eUICC
-     * will only have portId 0.
+     * Maps the logical slots to the SlotPortMapping, which consists of both physical slot id and
+     * port id. Logical slot is the slot that is seen by the modem. Physical slot is the actual
+     * physical slot. PortId is the id (enumerated value) for the associated port available on the
+     * SIM. Each physical slot can have multiple ports, which enables multi-enabled profile(MEP). If
+     * eUICC physical slot supports 2 ports, then the portId is numbered 0,1 and if eUICC2 supports
+     * 4 ports then the portID is numbered 0,1,2,3. Each portId is unique within a UICC physical
+     * slot but not necessarily unique across UICC’s. SEP(Single enabled profile) eUICC and
+     * non-eUICC will only have portId 0.
      *
      * Logical slots that are already mapped to the requested SlotPortMapping are not impacted.
      *
-     * Example no. of logical slots 1 and physical slots 2 do not support MEP, each physical slot
-     * has one port:
-     * The only logical slot (index 0) can be mapped to first physical slot (value 0), port(index
-     * 0). or second
-     * physical slot(value 1), port (index 0), while the other physical slot remains unmapped and
-     * inactive.
+     * Example: There is 1 logical slot, 2 physical slots, MEP is not supported and each physical
+     * slot has one port:
+     * The only logical slot (index 0) can be mapped to the first physical slot (value 0),
+     * port(index 0), or second physical slot(value 1), port (index 0), while the other physical
+     * slot remains unmapped and inactive.
      * slotMap[0] = SlotPortMapping{0 //physical slot//, 0 //port//}
      * slotMap[0] = SlotPortMapping{1 //physical slot//, 0 //port//}
      *
-     * Example no. of logical slots 2 and physical slots 2 supports MEP with 2 ports available:
-     * Each logical slot must be mapped to a port (physical slot and port combination).
-     * First logical slot (index 0) can be mapped to physical slot 1 and the second logical slot
-     * can be mapped to either port from physical slot 2.
+     * Example: There are 2 logical slots, 2 physical slots, MEP is supported and there are 2 ports
+     * available:
+     * Each logical slot must be mapped to a port (physical slot and port combination). The first
+     * logical slot (index 0) can be mapped to the physical slot 1 and the second logical slot can
+     * be mapped to either port from physical slot 2.
      *
      * slotMap[0] = SlotPortMapping{0, 0} and slotMap[1] = SlotPortMapping{1, 0} or
      * slotMap[0] = SlotPortMapping{0, 0} and slotMap[1] = SlotPortMapping{1, 1}
@@ -178,10 +179,10 @@
      *
      * @param serial Serial number of request
      * @param slotMap Logical to physical slot and port mapping.
-     *        Index is mapping to logical slot and value to physical slot and port id, need to
-     *        provide all the slots mapping when sending request in case of multi slot device.
+     *        The index maps to the logical slot, and the value to the physical slot and port id. In
+     *        the case of a multi-slot device, provide all the slot mappings when sending a request.
      *
-     *        EX: SlotPortMapping(physical slot, port id)
+     *        Example: SlotPortMapping(physical slot, port id)
      *        index 0 is the first logical_slot number of logical slots is equal to number of Radio
      *        instances and number of physical slots is equal to size of slotStatus in
      *        getSimSlotsStatusResponse
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl
index 9eacb8e..0b60dbb 100644
--- a/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl
@@ -27,9 +27,9 @@
     /**
      * Indicates SIM slot status change.
      *
-     * This indication must be sent by the modem whenever there is any slot status change, even the
-     * slot is inactive. For example, this indication must be triggered if a SIM card is inserted
-     * into an inactive slot.
+     * This indication must be sent by the modem whenever there is any slot status change, even if
+     * the slot is inactive. For example, this indication must be triggered if a SIM card is
+     * inserted into an inactive slot.
      *
      * @param type Type of radio indication
      * @param slotStatus new slot status info with size equals to the number of physical slots on
@@ -39,7 +39,7 @@
             in android.hardware.radio.RadioIndicationType type, in SimSlotStatus[] slotStatus);
 
     /**
-     * The logical slots supporting simultaneous cellular calling has changed.
+     * The logical slots supporting simultaneous cellular calling have changed.
      *
      * @param enabledLogicalSlots The slots that have simultaneous cellular calling enabled. If
      * there is a call active on logical slot X, then a simultaneous cellular call is only possible
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
index 33b0ff0..8182cd1 100644
--- a/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
@@ -26,18 +26,18 @@
 @VintfStability
 oneway interface IRadioConfigResponse {
     /**
-     * @param info Response info struct containing response type, serial no. and error
+     * @param info Response info struct containing response type, serial number and error
      * @param modemReducedFeatureSet1 True indicates that the modem does NOT support the following
-     *        features.
-     *        - Providing either LinkCapacityEstimate:secondaryDownlinkCapacityKbps
-     *          or LinkCapacityEstimate:secondaryUplinkCapacityKbps when given from
-     *          RadioIndication:currentLinkCapacityEstimate
-     *        - Calling IRadio.setNrDualConnectivityState or querying
-     *          IRadio.isNrDualConnectivityEnabled
-     *        - Requesting IRadio.setDataThrottling()
-     *        - Providing SlicingConfig through getSlicingConfig()
+     *        features:
+     *        - Providing either LinkCapacityEstimate#secondaryDownlinkCapacityKbps
+     *          or LinkCapacityEstimate#secondaryUplinkCapacityKbps when given from
+     *          IRadioNetworkIndication#currentLinkCapacityEstimate
+     *        - Calling IRadioNetwork#setNrDualConnectivityState or querying
+     *          IRadioNetwork#isNrDualConnectivityEnabled
+     *        - Requesting IRadioData#setDataThrottling
+     *        - Providing SlicingConfig through IRadioData#getSlicingConfig
      *        - Providing PhysicalChannelConfig through
-     *          IRadioIndication.currentPhysicalChannelConfigs_1_6()
+     *          IRadioNetworkIndication#currentPhysicalChannelConfigs
      *
      * Valid errors returned:
      *   RadioError:REQUEST_NOT_SUPPORTED when android.hardware.telephony is not defined
@@ -49,7 +49,7 @@
             in android.hardware.radio.RadioResponseInfo info, in boolean modemReducedFeatureSet1);
 
     /**
-     * @param info Response info struct containing response type, serial no. and error
+     * @param info Response info struct containing response type, serial number and error
      * @param numOfLiveModems <byte> indicate the number of live modems i.e. modems that
      *        are enabled and actively working as part of a working connectivity stack
      *
@@ -62,8 +62,8 @@
             in android.hardware.radio.RadioResponseInfo info, in byte numOfLiveModems);
 
     /**
-     * @param info Response info struct containing response type, serial no. and error
-     * @param phoneCapability <PhoneCapability> it defines modem's capability for example
+     * @param info Response info struct containing response type, serial number and error
+     * @param phoneCapability <PhoneCapability> it defines the modem's capability. For example,
      *        how many logical modems it has, how many data connections it supports.
      *
      * Valid errors returned:
@@ -76,7 +76,7 @@
             in android.hardware.radio.RadioResponseInfo info, in PhoneCapability phoneCapability);
 
     /**
-     * @param info Response info struct containing response type, serial no. and error
+     * @param info Response info struct containing response type, serial number and error
      * @param slotStatus Sim slot struct containing all the physical SIM slots info with size
      *        equal to the number of physical slots on the device
      *
@@ -93,7 +93,7 @@
             in android.hardware.radio.RadioResponseInfo info, in SimSlotStatus[] slotStatus);
 
     /**
-     * @param info Response info struct containing response type, serial no. and error
+     * @param info Response info struct containing response type, serial number and error
      *
      * Valid errors returned:
      *   RadioError:REQUEST_NOT_SUPPORTED when android.hardware.telephony is not defined
@@ -104,7 +104,7 @@
     void setNumOfLiveModemsResponse(in android.hardware.radio.RadioResponseInfo info);
 
     /**
-     * @param info Response info struct containing response type, serial no. and error
+     * @param info Response info struct containing response type, serial number and error
      *
      * Valid errors returned:
      *   RadioError:REQUEST_NOT_SUPPORTED when android.hardware.telephony.data is not defined
@@ -116,7 +116,7 @@
     void setPreferredDataModemResponse(in android.hardware.radio.RadioResponseInfo info);
 
     /**
-     * @param info Response info struct containing response type, serial no. and error
+     * @param info Response info struct containing response type, serial number and error
      *
      * Valid errors returned:
      *   RadioError:REQUEST_NOT_SUPPORTED when android.hardware.telephony.subscription is not
@@ -134,7 +134,7 @@
      * Response to the asynchronous
      * {@link IRadioConfig#getSimultaneousCallingSupport} request.
      *
-     * @param info Response info struct containing response type, serial no. and error
+     * @param info Response info struct containing response type, serial number and error
      * @param enabledLogicalSlots The slots that have simultaneous cellular calling enabled. If
      * there is a call active on logical slot X, then a simultaneous cellular call is only possible
      * on logical slot Y if BOTH slot X and slot Y are in enabledLogicalSlots. If simultaneous
diff --git a/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl b/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl
index 7936eb6..265ab96 100644
--- a/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl
+++ b/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl
@@ -17,8 +17,8 @@
 package android.hardware.radio.config;
 
 /**
- * Phone capability which describes the data connection capability of modem.
- * It's used to evaluate possible phone config change, for example from single
+ * Phone capability which describes the data connection capability of the modem.
+ * It's used to evaluate a possible phone config change, for example, from single
  * SIM device to multi-SIM device.
  * @hide
  */
@@ -27,21 +27,18 @@
 parcelable PhoneCapability {
     const byte UNKNOWN = -1;
     /**
-     * maxActiveData defines how many logical modems can have
-     * PS attached simultaneously. For example, for L+L modem it
-     * should be 2.
+     * maxActiveData defines how many logical modems can have PS attached simultaneously. For
+     * example, for a L+L modem, it should be 2.
      */
     byte maxActiveData;
     /**
-     * maxActiveData defines how many logical modems can have
-     * internet PDN connections simultaneously. For example, for L+L
-     * DSDS modem it’s 1, and for DSDA modem it’s 2.
+     * maxActiveInternetData defines how many logical modems can have internet PDN connections
+     * simultaneously. For example, for a L+L DSDS modem, it’s 1, and for a DSDA modem, it’s 2.
      */
     byte maxActiveInternetData;
     /**
-     * Whether modem supports both internet PDN up so
-     * that we can do ping test before tearing down the
-     * other one.
+     * Whether the modem supports both internet PDNs up, so that we can do a ping test on one PDN
+     * before tearing down the other PDN.
      */
     boolean isInternetLingeringSupported;
     /**
@@ -49,9 +46,8 @@
      */
     byte[] logicalModemIds;
     /**
-     * maxActiveVoice defines how many logical modems can have
-     * cellular voice calls simultaneously. For example, for cellular DSDA
-     * with simultaneous calling support, it should be 2.
+     * maxActiveVoice defines how many logical modems can have cellular voice calls simultaneously.
+     * For example, for cellular DSDA with simultaneous calling support, it should be 2.
      */
     byte maxActiveVoice = UNKNOWN;
 }
diff --git a/radio/aidl/android/hardware/radio/config/SimPortInfo.aidl b/radio/aidl/android/hardware/radio/config/SimPortInfo.aidl
index f579639..380932e 100644
--- a/radio/aidl/android/hardware/radio/config/SimPortInfo.aidl
+++ b/radio/aidl/android/hardware/radio/config/SimPortInfo.aidl
@@ -21,8 +21,8 @@
 @JavaDerive(toString=true)
 parcelable SimPortInfo {
     /**
-     * Integrated Circuit Card IDentifier (ICCID) is unique identifier of the SIM card. File is
-     * located in the SIM card at EFiccid (0x2FE2) as per ETSI 102.221. The ICCID is defined by
+     * Integrated Circuit Card IDentifier (ICCID) is the unique identifier of the SIM card. The file
+     * is located in the SIM card at EFiccid (0x2FE2) as per ETSI 102.221. The ICCID is defined by
      * the ITU-T recommendation E.118 ISO/IEC 7816.
      *
      * This data is applicable only when cardState is CardStatus.STATE_PRESENT.
@@ -33,13 +33,13 @@
      */
     String iccId;
     /**
-     * Logical slot id is identifier of the active slot
+     * The identifier of the active slot.
      */
     int logicalSlotId;
     /**
      * Port active status in the slot.
-     * Inactive means logical modem is no longer associated to the port.
-     * Active means logical modem is associated to the port.
+     * Inactive means that the logical modem is no longer associated to the port.
+     * Active means that the logical modem is associated to the port.
      */
     boolean portActive;
 }
diff --git a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
index 34f98c5..171d97a 100644
--- a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
+++ b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
@@ -46,12 +46,12 @@
     String eid;
     /**
      * PortInfo contains the ICCID, logical slot ID, and port state.
-     * Cardstate has no relationship with whether the slot is active or inactive. Should always
-     * report up at least 1 port otherwise the logicalSlotIndex and portActive info will be lost.
+     * Cardstate has no relationship with whether the slot is active or inactive. At least one port
+     * shall always be reported, otherwise the logicalSlotIndex and portActive info will be lost.
      * For example, the pSIM can be removed, but the slot can still be active. In that case, the
      * SIM_STATUS reported for the corresponding logical stack will show CARDSTATE_ABSENT.
-     * Similarly, even if there is no profile enabled on the eSIM, that port can still be the
-     * active port in the slot mapping.
+     * Similarly, even if there is no profile enabled on the eSIM, that port can still be the active
+     * port in the slot mapping.
      */
     SimPortInfo[] portInfo;
     /**
diff --git a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
index f44c636..bea8bcf 100644
--- a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
@@ -90,5 +90,13 @@
     /**
      * APN type for RCS (Rich Communication Services)
      */
-    RCS = 1 << 15
+    RCS = 1 << 15,
+    /**
+     * APN type for OEM_PAID networks (Automotive PANS)
+     */
+    OEM_PAID = 1 << 16,
+    /**
+     * APN type for OEM_PRIVATE networks (Automotive PANS)
+     */
+    OEM_PRIVATE = 1 << 17,
 }
diff --git a/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl b/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl
index e015e8e..6f043d9 100644
--- a/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl
@@ -20,6 +20,7 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum DataCallFailCause {
     /**
      * An integer cause code defined in TS 24.008 section 6.1.3.1.3 or TS 24.301 Release 8+ Annex B.
diff --git a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
index d01f8ff..f067fb4 100644
--- a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
@@ -66,15 +66,15 @@
     /**
      * PDP_type values.
      */
-    PdpProtocolType protocol;
+    PdpProtocolType protocol = PdpProtocolType.IP;
     /**
      * PDP_type values used on roaming network.
      */
-    PdpProtocolType roamingProtocol;
+    PdpProtocolType roamingProtocol = PdpProtocolType.IP;
     /**
      * APN authentication type.
      */
-    ApnAuthType authType;
+    ApnAuthType authType = ApnAuthType.NO_PAP_NO_CHAP;
     /**
      * The username for APN, or empty string.
      */
diff --git a/radio/aidl/android/hardware/radio/data/DataThrottlingAction.aidl b/radio/aidl/android/hardware/radio/data/DataThrottlingAction.aidl
index a762e34..03c3481 100644
--- a/radio/aidl/android/hardware/radio/data/DataThrottlingAction.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataThrottlingAction.aidl
@@ -20,6 +20,7 @@
 @VintfStability
 @Backing(type="byte")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum DataThrottlingAction {
     /*
      * Clear all existing data throttling.
diff --git a/radio/aidl/android/hardware/radio/data/KeepaliveRequest.aidl b/radio/aidl/android/hardware/radio/data/KeepaliveRequest.aidl
index 1838f2e..90c4454 100644
--- a/radio/aidl/android/hardware/radio/data/KeepaliveRequest.aidl
+++ b/radio/aidl/android/hardware/radio/data/KeepaliveRequest.aidl
@@ -40,7 +40,7 @@
     byte[] sourceAddress;
     /**
      * Source port if relevant for the given type
-     * INT_MAX: 0x7FFFFFFF denotes that the field is unused
+     * RadioConst:VALUE_UNAVAILABLE denotes that the field is unused
      */
     int sourcePort;
     /**
@@ -49,7 +49,7 @@
     byte[] destinationAddress;
     /**
      * Destination if relevant for the given type
-     * INT_MAX: 0x7FFFFFFF denotes that the field is unused
+     * RadioConst:VALUE_UNAVAILABLE denotes that the field is unused
      */
     int destinationPort;
     /**
diff --git a/radio/aidl/android/hardware/radio/data/LinkAddress.aidl b/radio/aidl/android/hardware/radio/data/LinkAddress.aidl
index 957973d..f5d6553 100644
--- a/radio/aidl/android/hardware/radio/data/LinkAddress.aidl
+++ b/radio/aidl/android/hardware/radio/data/LinkAddress.aidl
@@ -22,6 +22,7 @@
  */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable LinkAddress {
     const int ADDRESS_PROPERTY_NONE = 0;
     /**
@@ -44,14 +45,14 @@
      * The time, as reported by SystemClock.elapsedRealtime(), when this link address will be or
      * was deprecated. -1 indicates this information is not available. At the time existing
      * connections can still use this address until it expires, but new connections should use the
-     * new address. LONG_MAX(0x7FFFFFFFFFFFFFFF) indicates this link address will never be
+     * new address. RadioConst:VALUE_UNAVAILABLE_LONG indicates this link address will never be
      * deprecated.
      */
     long deprecationTime;
     /**
      * The time, as reported by SystemClock.elapsedRealtime(), when this link address will expire
      * and be removed from the interface. -1 indicates this information is not available.
-     * LONG_MAX(0x7FFFFFFFFFFFFFFF) indicates this link address will never expire.
+     * RadioConst:VALUE_UNAVAILABLE_LONG indicates this link address will never expire.
      */
     long expirationTime;
 }
diff --git a/radio/aidl/android/hardware/radio/data/PortRange.aidl b/radio/aidl/android/hardware/radio/data/PortRange.aidl
index 7326966..1d436fa 100644
--- a/radio/aidl/android/hardware/radio/data/PortRange.aidl
+++ b/radio/aidl/android/hardware/radio/data/PortRange.aidl
@@ -24,6 +24,7 @@
  */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable PortRange {
     const int PORT_RANGE_MIN = 20;
     const int PORT_RANGE_MAX = 65535;
diff --git a/radio/aidl/android/hardware/radio/data/RouteSelectionDescriptor.aidl b/radio/aidl/android/hardware/radio/data/RouteSelectionDescriptor.aidl
index 4e9e954..4d4b6d5 100644
--- a/radio/aidl/android/hardware/radio/data/RouteSelectionDescriptor.aidl
+++ b/radio/aidl/android/hardware/radio/data/RouteSelectionDescriptor.aidl
@@ -38,7 +38,7 @@
     /**
      * Valid values are IP, IPV6, IPV4V6, and UNKNOWN.
      */
-    PdpProtocolType sessionType;
+    PdpProtocolType sessionType = PdpProtocolType.IP;
     /**
      * Session and service continuity mode as defined in 3GPP TS 23.501.
      * Valid values are SSC_MODE_
diff --git a/radio/aidl/android/hardware/radio/data/SetupDataCallResult.aidl b/radio/aidl/android/hardware/radio/data/SetupDataCallResult.aidl
index b8f01c0..687982a 100644
--- a/radio/aidl/android/hardware/radio/data/SetupDataCallResult.aidl
+++ b/radio/aidl/android/hardware/radio/data/SetupDataCallResult.aidl
@@ -27,6 +27,7 @@
 /** @hide */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable SetupDataCallResult {
     /**
      * Indicates the data connection is inactive.
@@ -64,14 +65,14 @@
     /**
      * Data call fail cause. DataCallFailCause.NONE if no error.
      */
-    DataCallFailCause cause;
+    DataCallFailCause cause = DataCallFailCause.NONE;
     /**
      * If cause is not DataCallFailCause.NONE, this field indicates the network suggested data
      * retry back-off time in milliseconds. Negative value indicates network does not give any
-     * suggestion. 0 indicates retry should be performed immediately. 0x7fffffffffffffff indicates
-     * the device should not retry data setup anymore. During this time, no calls to
-     * IRadioData.setupDataCall for this APN will be made unless IRadioDataIndication.unthrottleApn
-     * is sent with the same APN.
+     * suggestion. 0 indicates retry should be performed immediately.
+     * RadioConst:VALUE_UNAVAILABLE_LONG indicates the device should not retry data setup anymore.
+     * During this time, no calls to IRadioData.setupDataCall for this APN will be made unless
+     * IRadioDataIndication.unthrottleApn is sent with the same APN.
      */
     long suggestedRetryTime;
     /**
@@ -87,7 +88,7 @@
      * PDP protocol type. If cause is DataCallFailCause.ONLY_SINGLE_BEARER_ALLOWED, this is the
      * protocol type supported, such as "IP" or "IPV6".
      */
-    PdpProtocolType type;
+    PdpProtocolType type = PdpProtocolType.IP;
     /**
      * The network interface name.
      */
diff --git a/radio/aidl/android/hardware/radio/ims/ConnectionFailureInfo.aidl b/radio/aidl/android/hardware/radio/ims/ConnectionFailureInfo.aidl
index c96f59f..92024ac 100644
--- a/radio/aidl/android/hardware/radio/ims/ConnectionFailureInfo.aidl
+++ b/radio/aidl/android/hardware/radio/ims/ConnectionFailureInfo.aidl
@@ -22,7 +22,10 @@
 parcelable ConnectionFailureInfo {
     @VintfStability
     @Backing(type="int")
+    @SuppressWarnings(value={"redundant-name"})
     enum ConnectionFailureReason {
+        /** Do not use. */
+        INVALID = 0,
         /** Access class check failed */
         REASON_ACCESS_DENIED = 1,
         /** 3GPP Non-access stratum failure */
@@ -47,7 +50,7 @@
     /**
      * Values are REASON_* constants
      */
-    ConnectionFailureReason failureReason;
+    ConnectionFailureReason failureReason = ConnectionFailureReason.INVALID;
 
     /**
      * Failure cause code from network or modem specific to the failure
diff --git a/radio/aidl/android/hardware/radio/ims/ImsCall.aidl b/radio/aidl/android/hardware/radio/ims/ImsCall.aidl
index 427c1f5..49fd62c 100644
--- a/radio/aidl/android/hardware/radio/ims/ImsCall.aidl
+++ b/radio/aidl/android/hardware/radio/ims/ImsCall.aidl
@@ -50,16 +50,16 @@
     int index;
 
     /** The type of the call */
-    CallType callType;
+    CallType callType = CallType.NORMAL;
 
     /** The access network where the call is in progress */
-    AccessNetwork accessNetwork;
+    AccessNetwork accessNetwork = AccessNetwork.UNKNOWN;
 
     /** The state of the call */
-    CallState callState;
+    CallState callState = CallState.ACTIVE;
 
     /** The direction of the call */
-    Direction direction;
+    Direction direction = Direction.INCOMING;
 
     /** True if the call is put on HOLD by the other party */
     boolean isHeldByRemote;
diff --git a/radio/aidl/android/hardware/radio/ims/ImsDeregistrationReason.aidl b/radio/aidl/android/hardware/radio/ims/ImsDeregistrationReason.aidl
index acfe51c..bee8276 100644
--- a/radio/aidl/android/hardware/radio/ims/ImsDeregistrationReason.aidl
+++ b/radio/aidl/android/hardware/radio/ims/ImsDeregistrationReason.aidl
@@ -20,6 +20,7 @@
 @VintfStability
 @JavaDerive(toString=true)
 @Backing(type="int")
+@SuppressWarnings(value={"redundant-name"})
 enum ImsDeregistrationReason {
     /**
      * Radio shall send this reason to IMS stack to perform graceful de-registration
diff --git a/radio/aidl/android/hardware/radio/ims/ImsRegistration.aidl b/radio/aidl/android/hardware/radio/ims/ImsRegistration.aidl
index 5158386..9018273 100644
--- a/radio/aidl/android/hardware/radio/ims/ImsRegistration.aidl
+++ b/radio/aidl/android/hardware/radio/ims/ImsRegistration.aidl
@@ -23,6 +23,7 @@
 /** @hide */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable ImsRegistration {
     /** Default value */
     const int IMS_MMTEL_CAPABILITY_NONE = 0;
@@ -36,15 +37,15 @@
     const int IMS_RCS_CAPABILITIES = 1 << 3;
 
     /** Indicates the current IMS registration state. */
-    ImsRegistrationState regState;
+    ImsRegistrationState regState = ImsRegistrationState.NOT_REGISTERED;
 
     /**
      * Indicates the type of the radio access network where IMS is registered.
      */
-    AccessNetwork accessNetworkType;
+    AccessNetwork accessNetworkType = AccessNetwork.UNKNOWN;
 
     /** Indicates the expected action for the radio to do. */
-    SuggestedAction suggestedAction;
+    SuggestedAction suggestedAction = SuggestedAction.NONE;
 
     /**
      * Values are bitwise ORs of IMS_MMTEL_CAPABILITY_* constants and IMS_RCS_CAPABILITIES.
diff --git a/radio/aidl/android/hardware/radio/ims/SrvccCall.aidl b/radio/aidl/android/hardware/radio/ims/SrvccCall.aidl
index 16858f9..4fdfed0 100644
--- a/radio/aidl/android/hardware/radio/ims/SrvccCall.aidl
+++ b/radio/aidl/android/hardware/radio/ims/SrvccCall.aidl
@@ -47,16 +47,16 @@
     int index;
 
     /** The type of the call */
-    CallType callType;
+    CallType callType = CallType.NORMAL;
 
     /** Values are android.hardware.radio.voice.Call.STATE_* constants */
     int callState;
 
     /** The substate of the call */
-    CallSubState callSubstate;
+    CallSubState callSubstate = CallSubState.NONE;
 
     /** The type of the ringback tone */
-    ToneType ringbackToneType;
+    ToneType ringbackToneType = ToneType.NONE;
 
     /** true if is mpty call */
     boolean isMpty;
diff --git a/radio/aidl/android/hardware/radio/ims/media/AmrMode.aidl b/radio/aidl/android/hardware/radio/ims/media/AmrMode.aidl
index dc2a162..94070db 100644
--- a/radio/aidl/android/hardware/radio/ims/media/AmrMode.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/AmrMode.aidl
@@ -23,7 +23,10 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum AmrMode {
+    /** Do not use. */
+    INVALID = 0,
     /** 4.75 kbps for AMR / 6.6 kbps for AMR-WB */
     AMR_MODE_0 = 1 << 0,
     /** 5.15 kbps for AMR / 8.855 kbps for AMR-WB */
diff --git a/radio/aidl/android/hardware/radio/ims/media/AmrParams.aidl b/radio/aidl/android/hardware/radio/ims/media/AmrParams.aidl
index 9d7ab05..dbf38c2 100644
--- a/radio/aidl/android/hardware/radio/ims/media/AmrParams.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/AmrParams.aidl
@@ -23,7 +23,7 @@
 @JavaDerive(toString=true)
 parcelable AmrParams {
     /** mode-set: AMR codec mode to represent the bit rate */
-    AmrMode amrMode;
+    AmrMode amrMode = AmrMode.INVALID;
     /**
      * octet-align: If it's set to true then all fields in the AMR/AMR-WB header
      * shall be aligned to octet boundaries by adding padding bits.
diff --git a/radio/aidl/android/hardware/radio/ims/media/CodecParams.aidl b/radio/aidl/android/hardware/radio/ims/media/CodecParams.aidl
index 74de6ec..6da8087 100644
--- a/radio/aidl/android/hardware/radio/ims/media/CodecParams.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/CodecParams.aidl
@@ -24,7 +24,7 @@
 @JavaDerive(toString=true)
 parcelable CodecParams {
     /** Negotiated codec type */
-    CodecType codecType;
+    CodecType codecType = CodecType.INVALID;
     /**
      * Static or dynamic payload type number negotiated through the SDP for
      * the incoming RTP packets. This value shall be matched with the PT value
diff --git a/radio/aidl/android/hardware/radio/ims/media/CodecType.aidl b/radio/aidl/android/hardware/radio/ims/media/CodecType.aidl
index 99fbac4..cf9dba4 100644
--- a/radio/aidl/android/hardware/radio/ims/media/CodecType.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/CodecType.aidl
@@ -21,6 +21,8 @@
 @Backing(type="int")
 @JavaDerive(toString=true)
 enum CodecType {
+    /** Do not use. */
+    INVALID = 0,
     /** Adaptive Multi-Rate */
     AMR = 1 << 0,
     /** Adaptive Multi-Rate Wide Band */
diff --git a/radio/aidl/android/hardware/radio/ims/media/EvsMode.aidl b/radio/aidl/android/hardware/radio/ims/media/EvsMode.aidl
index 12d981b..899f05a 100644
--- a/radio/aidl/android/hardware/radio/ims/media/EvsMode.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/EvsMode.aidl
@@ -23,7 +23,10 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum EvsMode {
+    /** Do not use. */
+    INVALID = 0,
     /** 6.6 kbps for EVS AMR-WB IO */
     EVS_MODE_0 = 1 << 0,
     /** 8.855 kbps for AMR-WB IO */
diff --git a/radio/aidl/android/hardware/radio/ims/media/EvsParams.aidl b/radio/aidl/android/hardware/radio/ims/media/EvsParams.aidl
index 52c3bf9..37c7d4b 100644
--- a/radio/aidl/android/hardware/radio/ims/media/EvsParams.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/EvsParams.aidl
@@ -24,10 +24,10 @@
 @JavaDerive(toString=true)
 parcelable EvsParams {
     /** EVS codec bandwidth */
-    EvsBandwidth bandwidth;
+    EvsBandwidth bandwidth = EvsBandwidth.NONE;
 
     /** mode-set: EVS codec mode to represent the bit rate */
-    EvsMode evsMode;
+    EvsMode evsMode = EvsMode.INVALID;
     /**
      * ch-aw-recv: Channel aware mode for the receive direction. Permissible values
      * are -1, 0, 2, 3, 5, and 7. If -1, channel-aware mode is disabled in the
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl b/radio/aidl/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
index 88180d7..c7ee147 100644
--- a/radio/aidl/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
@@ -23,6 +23,7 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum RtcpXrReportBlockType {
     /** Disable RTCP XR */
     RTCPXR_NONE = 0,
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtpConfig.aidl b/radio/aidl/android/hardware/radio/ims/media/RtpConfig.aidl
index 3c5c4dd..9aca292 100644
--- a/radio/aidl/android/hardware/radio/ims/media/RtpConfig.aidl
+++ b/radio/aidl/android/hardware/radio/ims/media/RtpConfig.aidl
@@ -29,7 +29,7 @@
     /** Media flow direction. The bitfield of MediaDirection(s) */
     int direction;
     /** Radio Access Network */
-    AccessNetwork accessNetwork;
+    AccessNetwork accessNetwork = AccessNetwork.UNKNOWN;
     /** IP address and port number of the other party for RTP media */
     RtpAddress remoteAddress;
     /** Negotiated session parameters */
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
index 19d84ff..8c494bb 100644
--- a/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
@@ -19,6 +19,7 @@
 /** @hide */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable CdmaSmsSubaddress {
     /**
      * CCITT X.213 or ISO 8348 AD2
diff --git a/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl b/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl
index 5f9f82b..bbcd1cb 100644
--- a/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl
@@ -24,7 +24,7 @@
 @VintfStability
 @JavaDerive(toString=true)
 parcelable ImsSmsMessage {
-    RadioTechnologyFamily tech;
+    RadioTechnologyFamily tech = RadioTechnologyFamily.THREE_GPP;
     /**
      * Retry if true
      */
diff --git a/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl b/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
index 7ca4021..6ad47fc 100644
--- a/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
+++ b/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
@@ -36,7 +36,7 @@
      * Radio access technology. Set UNKNOWN if the Activity statistics
      * is RAT independent.
      */
-    AccessNetwork rat;
+    AccessNetwork rat = AccessNetwork.UNKNOWN;
     /**
      * Frequency range. Values are FREQUENCY_RANGE_
      * Set FREQUENCY_RANGE_UNKNOWN if the Activity statistics when frequency range
diff --git a/radio/aidl/android/hardware/radio/modem/DeviceStateType.aidl b/radio/aidl/android/hardware/radio/modem/DeviceStateType.aidl
index c1f4cd6..86df920 100644
--- a/radio/aidl/android/hardware/radio/modem/DeviceStateType.aidl
+++ b/radio/aidl/android/hardware/radio/modem/DeviceStateType.aidl
@@ -20,6 +20,7 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum DeviceStateType {
     /**
      * Device power save mode (provided by PowerManager). True indicates the device is in
diff --git a/radio/aidl/android/hardware/radio/modem/HardwareConfigModem.aidl b/radio/aidl/android/hardware/radio/modem/HardwareConfigModem.aidl
index 1ba3562..0389170 100644
--- a/radio/aidl/android/hardware/radio/modem/HardwareConfigModem.aidl
+++ b/radio/aidl/android/hardware/radio/modem/HardwareConfigModem.aidl
@@ -32,9 +32,12 @@
      */
     int rilModel;
     /**
-     * Bitset value, based on RadioTechnology.
+     * All supported radio technologies.
+     *
+     * Despite the stated type, this is an int bitset: a mask where each bit position represents a
+     * radio technology.
      */
-    RadioTechnology rat;
+    RadioTechnology rat = RadioTechnology.UNKNOWN; // it's really an empty bitmask
     /**
      * Maximum number of concurrent active voice calls.
      */
diff --git a/radio/aidl/android/hardware/radio/modem/ImeiInfo.aidl b/radio/aidl/android/hardware/radio/modem/ImeiInfo.aidl
index 6d33505..82fade5 100644
--- a/radio/aidl/android/hardware/radio/modem/ImeiInfo.aidl
+++ b/radio/aidl/android/hardware/radio/modem/ImeiInfo.aidl
@@ -29,6 +29,8 @@
      * ImeiType enum is used identify the IMEI as primary or secondary as mentioned in GSMA TS.37
      */
     enum ImeiType {
+        /** Must not be used. */
+        INVALID = 0,
         /**
          * This is the primary IMEI of the device as mentioned in the GSMA TS.37. In a multi-SIM
          * device the modem must set one IMEI with this type as mentioned in GSMA TS37_2.2_REQ_8.
@@ -40,7 +42,7 @@
     }
 
     /** Primary or secondary IMEI as mentioned in GSMA spec TS.37 */
-    ImeiType type;
+    ImeiType type = ImeiType.INVALID;
     /**
      * IMEI value, see 3gpp spec 23.003 section 6. Note: This primary IMEI mapping must be
      * permanent throughout the lifetime of the device irrespective of the factory data reset,
diff --git a/radio/aidl/android/hardware/radio/modem/NvItem.aidl b/radio/aidl/android/hardware/radio/modem/NvItem.aidl
index b405137..d646ff7 100644
--- a/radio/aidl/android/hardware/radio/modem/NvItem.aidl
+++ b/radio/aidl/android/hardware/radio/modem/NvItem.aidl
@@ -17,7 +17,6 @@
 package android.hardware.radio.modem;
 
 /**
- * @deprecated NV APIs are deprecated starting from Android U.
  * @hide
  */
 @VintfStability
@@ -25,172 +24,217 @@
 @JavaDerive(toString=true)
 enum NvItem {
     /**
+     * @deprecated NV APIs are deprecated starting from Android U.
+     */
+    INVALID = 0,
+    /**
      * CDMA radio and account information (items 1-10)
      * CDMA MEID (hex)
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_MEID = 1,
     /**
      * CDMA MIN (MSID)
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_MIN = 2,
     /**
      * CDMA MDN
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_MDN = 3,
     /**
      * CDMA access overload control
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_ACCOLC = 4,
     /**
      * Carrier device provisioning (items 11-30)
      * Device MSL
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     DEVICE_MSL = 11,
     /**
      * RTN reconditioned status
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     RTN_RECONDITIONED_STATUS = 12,
     /**
      * RTN activation date
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     RTN_ACTIVATION_DATE = 13,
     /**
      * RTN life timer
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     RTN_LIFE_TIMER = 14,
     /**
      * RTN life calls
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     RTN_LIFE_CALLS = 15,
     /**
      * RTN life data TX
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     RTN_LIFE_DATA_TX = 16,
     /**
      * RTN life data RX
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     RTN_LIFE_DATA_RX = 17,
     /**
      * HFA in progress
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     OMADM_HFA_LEVEL = 18,
     /**
      * Mobile IP profile information (items 31-50)
      * NAI realm
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     MIP_PROFILE_NAI = 31,
     /**
      * MIP home address
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     MIP_PROFILE_HOME_ADDRESS = 32,
     /**
      * AAA auth
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     MIP_PROFILE_AAA_AUTH = 33,
     /**
      * HA auth
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     MIP_PROFILE_HA_AUTH = 34,
     /**
      * Primary HA address
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     MIP_PROFILE_PRI_HA_ADDR = 35,
     /**
      * Secondary HA address
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     MIP_PROFILE_SEC_HA_ADDR = 36,
     /**
      * Reverse TUN preference
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     MIP_PROFILE_REV_TUN_PREF = 37,
     /**
      * HA SPI
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     MIP_PROFILE_HA_SPI = 38,
     /**
      * AAA SPI
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     MIP_PROFILE_AAA_SPI = 39,
     /**
      * HA shared secret
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     MIP_PROFILE_MN_HA_SS = 40,
     /**
      * AAA shared secret
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     MIP_PROFILE_MN_AAA_SS = 41,
     /**
      * CDMA network and band config (items 51-70)
      * CDMA PRL version
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_PRL_VERSION = 51,
     /**
      * CDMA band class 10
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_BC10 = 52,
     /**
      * CDMA band class 14
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_BC14 = 53,
     /**
      * CDMA SO68
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_SO68 = 54,
     /**
      * CDMA SO73 COP0
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_SO73_COP0 = 55,
     /**
      * CDMA SO73 COP1-7
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_SO73_COP1TO7 = 56,
     /**
      * CDMA 1X Advanced enabled
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_1X_ADVANCED_ENABLED = 57,
     /**
      * CDMA eHRPD enabled
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_EHRPD_ENABLED = 58,
     /**
      * CDMA eHRPD forced
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     CDMA_EHRPD_FORCED = 59,
     /**
      * LTE network and band config (items 71-90)
      * LTE band 25 enabled
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     LTE_BAND_ENABLE_25 = 71,
     /**
      * LTE band 26 enabled
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     LTE_BAND_ENABLE_26 = 72,
     /**
      * LTE band 41 enabled
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     LTE_BAND_ENABLE_41 = 73,
     /**
      * LTE band 25 scan priority
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     LTE_SCAN_PRIORITY_25 = 74,
     /**
      * LTE band 26 scan priority
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     LTE_SCAN_PRIORITY_26 = 75,
     /**
      * LTE band 41 scan priority
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     LTE_SCAN_PRIORITY_41 = 76,
     /**
      * LTE hidden band 25 priority
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     LTE_HIDDEN_BAND_PRIORITY_25 = 77,
     /**
      * LTE hidden band 26 priority
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     LTE_HIDDEN_BAND_PRIORITY_26 = 78,
     /**
      * LTE hidden band 41 priority
+     * @deprecated NV APIs are deprecated starting from Android U.
      */
     LTE_HIDDEN_BAND_PRIORITY_41 = 79,
 }
diff --git a/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl b/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl
index c57253b..482126a 100644
--- a/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl
+++ b/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl
@@ -19,12 +19,17 @@
 import android.hardware.radio.modem.NvItem;
 
 /**
- * @deprecated NV APIs are deprecated starting from Android U.
  * @hide
  */
 @VintfStability
 @JavaDerive(toString=true)
 parcelable NvWriteItem {
-    NvItem itemId;
+    /**
+     * @deprecated NV APIs are deprecated starting from Android U.
+     */
+    NvItem itemId = NvItem.INVALID;
+    /**
+     * @deprecated NV APIs are deprecated starting from Android U.
+     */
     String value;
 }
diff --git a/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl b/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl
index e290a52..b6be54d 100644
--- a/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl
+++ b/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl
@@ -23,6 +23,7 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum ResetNvType {
     /**
      * Reload all NV items
diff --git a/radio/aidl/android/hardware/radio/network/BarringInfo.aidl b/radio/aidl/android/hardware/radio/network/BarringInfo.aidl
index f12e35c..7be3987 100644
--- a/radio/aidl/android/hardware/radio/network/BarringInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/BarringInfo.aidl
@@ -21,6 +21,7 @@
 /** @hide */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable BarringInfo {
     /**
      * Device is not barred for the given service
diff --git a/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl
index ae7aa93..0e241d3 100644
--- a/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl
@@ -22,12 +22,12 @@
 parcelable CdmaSignalStrength {
     /**
      * This value is the actual RSSI value multiplied by -1. Example: If the actual RSSI is -75,
-     * then this response value will be 75. INT_MAX means invalid/unreported.
+     * then this response value will be 75. RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int dbm;
     /**
      * This value is the actual Ec/Io multiplied by -10. Example: If the actual Ec/Io is -12.5 dB,
-     * then this response value will be 125. INT_MAX means invalid/unreported.
+     * then this response value will be 125. RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int ecio;
 }
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl
index b93988f..acf3db1 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl
@@ -23,27 +23,27 @@
 @JavaDerive(toString=true)
 parcelable CellIdentityCdma {
     /**
-     * Network Id 0..65535, INT_MAX if unknown
+     * Network Id 0..65535, RadioConst:VALUE_UNAVAILABLE if unknown
      */
     int networkId;
     /**
-     * CDMA System Id 0..32767, INT_MAX if unknown
+     * CDMA System Id 0..32767, RadioConst:VALUE_UNAVAILABLE if unknown
      */
     int systemId;
     /**
-     * Base Station Id 0..65535, INT_MAX if unknown
+     * Base Station Id 0..65535, RadioConst:VALUE_UNAVAILABLE if unknown
      */
     int baseStationId;
     /**
      * Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0. It is represented in
      * units of 0.25 seconds and ranges from -2592000 to 2592000, both values inclusive
-     * (corresponding to a range of -180 to +180 degrees). INT_MAX if unknown
+     * (corresponding to a range of -180 to +180 degrees). RadioConst:VALUE_UNAVAILABLE if unknown
      */
     int longitude;
     /**
      * Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0. It is represented in
      * units of 0.25 seconds and ranges from -1296000 to 1296000, both values inclusive
-     * (corresponding to a range of -90 to +90 degrees). INT_MAX if unknown
+     * (corresponding to a range of -90 to +90 degrees). RadioConst:VALUE_UNAVAILABLE if unknown
      */
     int latitude;
     /**
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityGsm.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityGsm.aidl
index bc02adc..fe39a0e 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityGsm.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityGsm.aidl
@@ -31,11 +31,12 @@
      */
     String mnc;
     /**
-     * 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+     * 16-bit Location Area Code, 0..65535, RadioConst:VALUE_UNAVAILABLE if unknown
      */
     int lac;
     /**
-     * 16-bit GSM Cell Identity described in TS 27.007, 0..65535, INT_MAX if unknown
+     * 16-bit GSM Cell Identity described in TS 27.007, 0..65535,
+     * RadioConst:VALUE_UNAVAILABLE if unknown
      */
     int cid;
     /**
@@ -43,7 +44,7 @@
      */
     int arfcn;
     /**
-     * 6-bit Base Station Identity Code, 0xFF if unknown
+     * 6-bit Base Station Identity Code, RadioConst:VALUE_UNAVAILABLE_BYTE if unknown
      */
     byte bsic;
     /**
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityLte.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityLte.aidl
index 27c2580..9c4fc3c 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityLte.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityLte.aidl
@@ -33,7 +33,7 @@
      */
     String mnc;
     /**
-     * 28-bit Cell Identity described in TS TS 27.007, INT_MAX if unknown
+     * 28-bit Cell Identity described in TS 27.007, RadioConst:VALUE_UNAVAILABLE if unknown
      */
     int ci;
     /**
@@ -41,7 +41,7 @@
      */
     int pci;
     /**
-     * 16-bit tracking area code, INT_MAX if unknown
+     * 16-bit tracking area code, RadioConst:VALUE_UNAVAILABLE if unknown
      */
     int tac;
     /**
@@ -53,7 +53,7 @@
      */
     OperatorInfo operatorNames;
     /**
-     * Cell bandwidth, in kHz.
+     * Cell bandwidth, in kHz. Must be valid as described in TS 36.101 5.6.
      */
     int bandwidth;
     /**
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityNr.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityNr.aidl
index 4192845..7ebc0cd 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityNr.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityNr.aidl
@@ -29,12 +29,12 @@
 parcelable CellIdentityNr {
     /**
      * 3-digit Mobile Country Code, in range[0, 999]; This value must be valid for registered or
-     *  camped cells; INT_MAX means invalid/unreported.
+     *  camped cells; Empty string means invalid/unreported.
      */
     String mcc;
     /**
      * 2 or 3-digit Mobile Network Code, in range [0, 999], This value must be valid for
-     * registered or camped cells; INT_MAX means invalid/unreported.
+     * registered or camped cells; Empty string means invalid/unreported.
      */
     String mnc;
     /**
@@ -48,7 +48,7 @@
      */
     int pci;
     /**
-     * 16-bit tracking area code, INT_MAX means invalid/unreported.
+     * 16-bit tracking area code, RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int tac;
     /**
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityTdscdma.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityTdscdma.aidl
index 33ffc6f..8373493 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityTdscdma.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityTdscdma.aidl
@@ -32,15 +32,17 @@
      */
     String mnc;
     /**
-     * 16-bit Location Area Code, 0..65535, INT_MAX if unknown.
+     * 16-bit Location Area Code, 0..65535, RadioConst:VALUE_UNAVAILABLE if unknown.
      */
     int lac;
     /**
-     * 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown.
+     * 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, RadioConst:VALUE_UNAVAILABLE
+     * if unknown.
      */
     int cid;
     /**
-     * 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown.
+     * 8-bit Cell Parameters ID described in TS 25.331, 0..127, RadioConst:VALUE_UNAVAILABLE if
+     * unknown.
      */
     int cpid;
     /**
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityWcdma.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityWcdma.aidl
index b6e328a..ab703f1 100644
--- a/radio/aidl/android/hardware/radio/network/CellIdentityWcdma.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityWcdma.aidl
@@ -32,11 +32,12 @@
      */
     String mnc;
     /**
-     * 16-bit Location Area Code, 0..65535, INT_MAX if unknown.
+     * 16-bit Location Area Code, 0..65535, RadioConst:VALUE_UNAVAILABLE if unknown.
      */
     int lac;
     /**
-     * 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown.
+     * 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, RadioConst:VALUE_UNAVAILABLE
+     * if unknown.
      */
     int cid;
     /**
diff --git a/radio/aidl/android/hardware/radio/network/CellInfo.aidl b/radio/aidl/android/hardware/radio/network/CellInfo.aidl
index 4895326..808a407 100644
--- a/radio/aidl/android/hardware/radio/network/CellInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellInfo.aidl
@@ -30,6 +30,6 @@
     /**
      * Connection status for the cell.
      */
-    CellConnectionStatus connectionStatus;
+    CellConnectionStatus connectionStatus = CellConnectionStatus.NONE;
     CellInfoRatSpecificInfo ratSpecificInfo;
 }
diff --git a/radio/aidl/android/hardware/radio/network/CellularIdentifierDisclosure.aidl b/radio/aidl/android/hardware/radio/network/CellularIdentifierDisclosure.aidl
index 52b4116..c851b43 100644
--- a/radio/aidl/android/hardware/radio/network/CellularIdentifierDisclosure.aidl
+++ b/radio/aidl/android/hardware/radio/network/CellularIdentifierDisclosure.aidl
@@ -31,9 +31,9 @@
     // The PLMN-ID to which the UE transmitted the cellular identifier
     String plmn;
     // The type of cellular identifier that was disclosed
-    CellularIdentifier identifier;
+    CellularIdentifier identifier = CellularIdentifier.UNKNOWN;
     // The NAS protocol message within which the cellular identifier was transmitted.
-    NasProtocolMessage protocolMessage;
+    NasProtocolMessage protocolMessage = NasProtocolMessage.UNKNOWN;
     // Whether or not this cellular identifier disclosure is in service of an emergency call.
     boolean isEmergency;
 }
diff --git a/radio/aidl/android/hardware/radio/network/Domain.aidl b/radio/aidl/android/hardware/radio/network/Domain.aidl
index bb169bd..e420e7b 100644
--- a/radio/aidl/android/hardware/radio/network/Domain.aidl
+++ b/radio/aidl/android/hardware/radio/network/Domain.aidl
@@ -21,6 +21,8 @@
 @Backing(type="int")
 @JavaDerive(toString=true)
 enum Domain {
+    /** Do not use. */
+    INVALID = 0,
     /**
      * Circuit-switched
      */
diff --git a/radio/aidl/android/hardware/radio/network/EmergencyMode.aidl b/radio/aidl/android/hardware/radio/network/EmergencyMode.aidl
index 7a2ed9c..bd36494 100644
--- a/radio/aidl/android/hardware/radio/network/EmergencyMode.aidl
+++ b/radio/aidl/android/hardware/radio/network/EmergencyMode.aidl
@@ -20,6 +20,7 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum EmergencyMode {
     /**
      * Mode Type Emergency WWAN, indicates that the current domain selected for the Emergency call
diff --git a/radio/aidl/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl b/radio/aidl/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl
index ea4bfeb..572d1e2 100644
--- a/radio/aidl/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl
+++ b/radio/aidl/android/hardware/radio/network/EmergencyNetworkScanTrigger.aidl
@@ -32,5 +32,5 @@
      * Scan type indicates the type of scans to be performed i.e. limited scan, full service scan or
      * any scan.
      */
-    EmergencyScanType scanType;
+    EmergencyScanType scanType = EmergencyScanType.NO_PREFERENCE;
 }
diff --git a/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl b/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl
index af2750e..7fc4d26 100644
--- a/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl
+++ b/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl
@@ -26,17 +26,17 @@
     /**
      * Indicates the cellular access network of the current emergency capable system.
      */
-    AccessNetwork accessNetwork;
+    AccessNetwork accessNetwork = AccessNetwork.UNKNOWN;
 
     /**
      * Registration state of the current emergency capable system.
      */
-    RegState regState;
+    RegState regState = RegState.NOT_REG_MT_NOT_SEARCHING_OP;
 
     /**
      * EMC domain indicates the current domain of the acquired system.
      */
-    Domain emcDomain;
+    Domain emcDomain = Domain.INVALID;
 
     /**
      * This indicates whether the network supports voice over PS network.
diff --git a/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl b/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl
index fb319c1..15fabf3 100644
--- a/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl
@@ -54,7 +54,7 @@
      * The type of network attachment. This info is valid only on LTE network and must be present
      * when device has attached to the network.
      */
-    AttachResultType lteAttachResultType;
+    AttachResultType lteAttachResultType = AttachResultType.NONE;
 
     /** Values are bitwise ORs of EXTRA_* constants */
     int extraInfo;
diff --git a/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl
index fc7cc1b..ac6928e 100644
--- a/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl
@@ -22,17 +22,17 @@
 parcelable EvdoSignalStrength {
     /**
      * This value is the actual RSSI value multiplied by -1. Example: If the actual RSSI is -75,
-     * then this response value will be 75; INT_MAX means invalid/unreported.
+     * then this response value will be 75; RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int dbm;
     /**
      * This value is the actual Ec/Io multiplied by -10. Example: If the actual Ec/Io is -12.5 dB,
-     * then this response value will be 125; INT_MAX means invalid/unreported.
+     * then this response value will be 125; RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int ecio;
     /**
-     * Valid values are 0-8. 8 is the highest signal to noise ratio; INT_MAX means
-     * invalid/unreported.
+     * Valid values are 0-8. 8 is the highest signal to noise ratio; RadioConst:VALUE_UNAVAILABLE
+     * means invalid/unreported.
      */
     int signalNoiseRatio;
 }
diff --git a/radio/aidl/android/hardware/radio/network/GsmSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/GsmSignalStrength.aidl
index d569cf7..4a99646 100644
--- a/radio/aidl/android/hardware/radio/network/GsmSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/GsmSignalStrength.aidl
@@ -21,15 +21,18 @@
 @JavaDerive(toString=true)
 parcelable GsmSignalStrength {
     /**
-     * Valid values are (0-61, 99) as defined in TS 27.007 8.69; INT_MAX means invalid/unreported.
+     * Valid values are (0-61, 99) as defined in TS 27.007 8.69; RadioConst:VALUE_UNAVAILABLE means
+     * invalid/unreported.
      */
     int signalStrength;
     /**
-     * Bit error rate (0-7, 99) as defined in TS 27.007 8.5; INT_MAX means invalid/unreported.
+     * Bit error rate (0-7, 99) as defined in TS 27.007 8.5; RadioConst:VALUE_UNAVAILABLE means
+     * invalid/unreported.
      */
     int bitErrorRate;
     /**
-     * Timing advance in bit periods. 1 bit period = 48/13 us. INT_MAX means invalid/unreported.
+     * Timing advance in bit periods. 1 bit period = 48/13 us. RadioConst:VALUE_UNAVAILABLE means
+     * invalid/unreported.
      */
     int timingAdvance;
 }
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index 5f26195..81d21e1 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -278,7 +278,7 @@
     /**
      * Sets the minimum time between when unsolicited cellInfoList() must be invoked.
      * A value of 0, means invoke cellInfoList() when any of the reported information changes.
-     * Setting the value to INT_MAX(0x7fffffff) means never issue a unsolicited cellInfoList().
+     * Value of RadioConst:VALUE_UNAVAILABLE means never issue a unsolicited cellInfoList().
      *
      * @param serial Serial number of request.
      * @param rate minimum time in milliseconds to indicate time between unsolicited cellInfoList()
@@ -503,7 +503,7 @@
      *
      * This is available when android.hardware.telephony is defined.
      */
-    oneway void setUsageSetting(in int serial, in UsageSetting usageSetting);
+    void setUsageSetting(in int serial, in UsageSetting usageSetting);
 
     /**
      * Get the UE usage setting for data/voice centric usage.
@@ -514,7 +514,7 @@
      *
      * This is available when android.hardware.telephony is defined.
      */
-    oneway void getUsageSetting(in int serial);
+    void getUsageSetting(in int serial);
 
     /**
      * Set the Emergency Mode
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
index da82b78..7b6fc6e 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
@@ -221,6 +221,12 @@
      * - If a device uses a 2G network to send a AUTHENTICATION_AND_CIPHERING_RESPONSE message on
      * the NAS and the message includes an IMEISV.
      *
+     * cellularIdentifierDisclosure indications must be sent to Android regardless of the screen
+     * state. If the screen is off, the indications must still be sent to Android.
+     *
+     * Note: in the NRSA scenario, only a SUCI generated by a null scheme should be considered as a
+     * plain-text identifier.
+     *
      * @param type Type of radio indication
      * @param disclosure A CellularIdentifierDisclosure as specified by
      *         IRadioNetwork.setCellularIdentifierTransparencyEnabled.
@@ -232,23 +238,78 @@
     /*
      * Indicates that a new ciphering or integrity algorithm was used for a particular voice,
      * signaling, or data connection for a given PLMN and/or access network. Due to power
-     * concerns, once a connection type has been reported on, follow-up reports about that
-     * connection type are only generated if there is any change to the most-recently reported
-     * encryption or integrity, or if the value of SecurityAlgorithmUpdate#isUnprotectedEmergency
-     * changes. A change only in cell ID should not trigger an update, as the design is intended
-     * to be agnostic to dual connectivity ("secondary serving cells").
+     * concerns, once a ConnectionEvent has been reported on, follow-up reports about that
+     * ConnectionEvent are only generated if there is any change to the most-recently reported
+     * encryption or integrity, if there is a RAT change, or if the value of
+     * SecurityAlgorithmUpdate#isUnprotectedEmergency changes. A change only in cell ID should not
+     * trigger an update, as the design is intended to be agnostic to dual connectivity ("secondary
+     * serving cells").
      *
-     * Sample scenario to further clarify "most-recently reported":
+     * Example to further clarify "most-recently reported":
+     * 1. After booting up, the UE is in ENDC with LTE. Modem reports NAS_SIGNALLING_LTE and
+     *    AS_SIGNALLING_LTE are well-ciphered but AS_SIGNALLING_5G is null-ciphered.
+     * 2. UE moves to 3G and enters the connected mode. Modem reports indications of PS_SERVICE_3G
+     *    and SIGNALLING_3G to Android.
+     * 3. UE moves to LTE. UE enters the connected mode and there is no ENDC. The algorithms of
+     *    NAS_SIGNALLING_LTE and AS_SIGNALLING_LTE are the same as in Step 1. The UE should send
+     *    this indication to AP as it’s a RAT switch.
+     * 4. Later, UE establishes ENDC. AS_SIGNALLING_5G is null-ciphered. The UE should send this
+     *    indication as well, as it is a RAT switch.
+     * 5. The UE enter IDLE mode, and later connected mode in ENDC. There are no changes to security
+     *    algorithms, so the modem does not need to send any updates.
      *
-     * 1. Modem reports user is connected to a null-ciphered 3G network.
-     * 2. User then moves and connects to a well-ciphered 5G network, and modem reports this.
-     * 3. User returns to original location and reconnects to the null-ciphered 3G network. Modem
-     *    should report this as it's different than the most-recently reported data from step (2).
+     * Most recently reported state is reset when (1) RadioState is transitioned to ON from any
+     * other state (e.g. radio is turned on during device boot, or modem boot), and (2) when
+     * CardState is transitioned to PRESENT from any other state (e.g. when SIM is inserted), or (3)
+     * if there is a change in access network (PLMN) or RAT.
      *
-     * State is reset when (1) RadioState is transitioned to ON from any other state (e.g. radio
-     * is turned on during device boot, or modem boot), and (2) when CardState is transitioned
-     * to PRESENT from any other state (e.g. when SIM is inserted), or (3) if there is a change in
-     * access network (PLMN).
+     * securityAlgorithmUpdate indications must be sent to Android regardless of the screen state.
+     * If the screen is off, the indications must still be sent to Android.
+     *
+     *
+     * 5G TS 38.331 cipheringDisabled and integrityProtection
+     * ======================================================
+     * For most connections, generally what is reported by the network is what ends up being used.
+     * There are two significant cases where this may not be the case. In 5G, per the introduction
+     * of network configuration options cipheringDisabled and integrityProtection (TS 38.331), the
+     * network can have declared certain security algorithms to be used while also requiring a null
+     * algorithm via those parameters.
+     *
+     *
+     * Exceptions for DRBs with null integrity (pre-5G Rel 16)
+     * =======================================================
+     * When reporting the SecurityAlgorithm for a ConnectionType which includes a DRB, there is an
+     * exception where a DRB with null integrity is not to be considered/included in reporting
+     * except for 5G Rel 16 connections and newer. Because DRBs almost always use null integrity in
+     * practice, and thus if included the report would always be null, rendering the report
+     * useless. For anything 5G Rel 16 or newer, accurate reporting for the DRB's integrity is
+     * required.
+     *
+     *
+     * NRDC MCG and SCGs
+     * =================
+     * In the NRDC case, there can be two sets of algorithms, one for the MCG (Master Cell Group)
+     * and one for the SCG (Secondary Cell Group). In this case, always send a combined update that
+     * reflects the weaker of the algorithms, e.g. (weakest) NEA0 < NEA1 < NEA2 < NEA3 (strongest).
+     * This applies to both the ciphering and integrity algorithms.
+     *
+     *
+     * Determining the value of isUnprotectedEmergency
+     * ===============================================
+     * 2G: isUnprotectedEmergency is true if the ciphering algorithm is NULL.
+     * 3G: isUnprotectedEmergency is true if the ciphering and integrity algorithm are NULL.
+     * 4G: isUnprotectedEmergency is true if the ciphering algorithm is NULL.
+     * 5G: isUnprotectedEmergency is true if the ciphering algorithm is NULL.
+     * Notes:
+     *    - On integrity: In 4G, PDCP can be LTE-based or NR-based. Starting from 5G Rel 17, only
+     *      the NR-based PDCP supports DRB integrity. As the PDCP version can change during a DRB's
+     *      operation, it becomes complicated when integrity is used to determine whether an
+     *      emergency call is protected or not, hence its exclusion to simplify implementation.
+     *    - 4G and 5G with multiple DRBs : emergency calls are protected under that RAT only if all
+     *      SRBs and DRBs are protected (including IMS DRB).
+     *    - 4G and 5G DRB integrity: Since DRB integrity is not enabled in most networks, if both
+     *      ciphering and integrity are taken into account to determine the value of
+     *      isUnprotectedEmergency, the value will mostly be false, hence why it is excluded.
      *
      * @param type Type of radio indication
      * @param securityAlgorithmUpdate SecurityAlgorithmUpdate encapsulates details of security
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index b67e8e0..5dcdb69 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -603,7 +603,7 @@
      *   RadioError:INTERNAL_ERR
      *   RadioError:SIM_ABSENT
      */
-    oneway void setUsageSettingResponse(in RadioResponseInfo info);
+    void setUsageSettingResponse(in RadioResponseInfo info);
 
     /**
      * @param info Response info struct containing response type, serial no. and error.
@@ -617,7 +617,7 @@
      *   RadioError:INTERNAL_ERR
      *   RadioError:SIM_ABSENT
      */
-    oneway void getUsageSettingResponse(in RadioResponseInfo info, in UsageSetting usageSetting);
+    void getUsageSettingResponse(in RadioResponseInfo info, in UsageSetting usageSetting);
 
     /**
      * Response of setEmergencyMode.
diff --git a/radio/aidl/android/hardware/radio/network/LteSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/LteSignalStrength.aidl
index 21d3ec7..785db0b 100644
--- a/radio/aidl/android/hardware/radio/network/LteSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/LteSignalStrength.aidl
@@ -21,41 +21,43 @@
 @JavaDerive(toString=true)
 parcelable LteSignalStrength {
     /**
-     * Valid values are (0-31, 99) as defined in TS 27.007 8.5; INT_MAX means invalid/unreported.
+     * Valid values are (0-31, 99) as defined in TS 27.007 8.5;
+     * RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int signalStrength;
     /**
      * The current Reference Signal Receive Power in dBm multiplied by -1. Range: 44 to 140 dBm;
-     * INT_MAX: 0x7FFFFFFF denotes invalid/unreported value. Reference: 3GPP TS 36.133 9.1.4
+     * RadioConst:VALUE_UNAVAILABLE denotes invalid/unreported value. Ref: 3GPP TS 36.133 9.1.4
      */
     int rsrp;
     /**
      * The current Reference Signal Receive Quality in dB multiplied by -1. Range: 20 to 3 dB;
-     * INT_MAX: 0x7FFFFFFF denotes invalid/unreported value. Reference: 3GPP TS 36.133 9.1.7
+     * RadioConst:VALUE_UNAVAILABLE denotes invalid/unreported value. Ref: 3GPP TS 36.133 9.1.7
      */
     int rsrq;
     /**
      * The current reference signal signal-to-noise ratio in 0.1 dB units.
      * Range: -200 to +300 (-200 = -20.0 dB, +300 = 30dB).
-     * INT_MAX: 0x7FFFFFFF denotes invalid/unreported value. Reference: 3GPP TS 36.101 8.1.1
+     * RadioConst:VALUE_UNAVAILABLE denotes invalid/unreported value. Ref: 3GPP TS 36.101 8.1.1
      */
     int rssnr;
     /**
      * The current Channel Quality Indicator. Range: 0 to 15.
-     * INT_MAX: 0x7FFFFFFF denotes invalid/unreported value. Reference: 3GPP TS 36.101 9.2, 9.3, A.4
+     * RadioConst:VALUE_UNAVAILABLE denotes invalid/unreported value.
+     * Ref: 3GPP TS 36.101 9.2, 9.3, A.4
      */
     int cqi;
     /**
      * Timing advance in micro seconds for a one way trip from cell to device. Approximate distance
      * is calculated using 300m/us * timingAdvance. Range: 0 to 1282 inclusive.
-     * INT_MAX: 0x7FFFFFFF denotes invalid/unreported value. Reference: 3GPP 36.213 section 4.2.3
+     * RadioConst:VALUE_UNAVAILABLE denotes invalid/unreported value. Ref: 3GPP 36.213 section 4.2.3
      */
     int timingAdvance;
     /**
      * CSI channel quality indicator (CQI) table index. There are multiple CQI tables.
      * The definition of CQI in each table is different.
      * Reference: 3GPP TS 136.213 section 7.2.3.
-     * Range [1, 6], INT_MAX means invalid/unreported.
+     * Range [1, 6], RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int cqiTableIndex;
 }
diff --git a/radio/aidl/android/hardware/radio/network/NetworkScanRequest.aidl b/radio/aidl/android/hardware/radio/network/NetworkScanRequest.aidl
index 37f2cf1..30977f8 100644
--- a/radio/aidl/android/hardware/radio/network/NetworkScanRequest.aidl
+++ b/radio/aidl/android/hardware/radio/network/NetworkScanRequest.aidl
@@ -21,6 +21,7 @@
 /** @hide */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable NetworkScanRequest {
     const int RADIO_ACCESS_SPECIFIER_MAX_SIZE = 8;
 
diff --git a/radio/aidl/android/hardware/radio/network/NetworkScanResult.aidl b/radio/aidl/android/hardware/radio/network/NetworkScanResult.aidl
index 4465046..700c5e2 100644
--- a/radio/aidl/android/hardware/radio/network/NetworkScanResult.aidl
+++ b/radio/aidl/android/hardware/radio/network/NetworkScanResult.aidl
@@ -22,6 +22,7 @@
 /** @hide */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable NetworkScanResult {
     /**
      * The result contains a part of the scan results.
@@ -40,7 +41,7 @@
     /**
      * The error code of the incremental result.
      */
-    RadioError error;
+    RadioError error = RadioError.NONE;
     /**
      * List of network information as CellInfo.
      */
diff --git a/radio/aidl/android/hardware/radio/network/NrSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/NrSignalStrength.aidl
index 65daf36..a0db2d5 100644
--- a/radio/aidl/android/hardware/radio/network/NrSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/NrSignalStrength.aidl
@@ -16,6 +16,8 @@
 
 package android.hardware.radio.network;
 
+import android.hardware.radio.RadioConst;
+
 /** @hide */
 @VintfStability
 @JavaDerive(toString=true)
@@ -23,44 +25,44 @@
     /**
      * SS reference signal received power, multiplied by -1.
      * Reference: 3GPP TS 38.215.
-     * Range [44, 140], INT_MAX means invalid/unreported.
+     * Range [44, 140], RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int ssRsrp;
     /**
      * SS reference signal received quality, multiplied by -1.
      * Reference: 3GPP TS 38.215, 3GPP TS 38.133 section 10.
-     * Range [-20 dB, 43 dB], INT_MAX means invalid/unreported.
+     * Range [-20 dB, 43 dB], RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int ssRsrq;
     /**
      * SS signal-to-noise and interference ratio.
      * Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
-     * Range [-23, 40], INT_MAX means invalid/unreported.
+     * Range [-23, 40], RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int ssSinr;
     /**
      * CSI reference signal received power, multiplied by -1.
      * Reference: 3GPP TS 38.215.
-     * Range [44, 140], INT_MAX means invalid/unreported.
+     * Range [44, 140], RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int csiRsrp;
     /**
      * CSI reference signal received quality, multiplied by -1.
      * Reference: 3GPP TS 38.215.
-     * Range [3, 20], INT_MAX means invalid/unreported.
+     * Range [3, 20], RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int csiRsrq;
     /**
      * CSI signal-to-noise and interference ratio.
      * Reference: 3GPP TS 138.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
-     * Range [-23, 40], INT_MAX means invalid/unreported.
+     * Range [-23, 40], RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int csiSinr;
     /**
      * CSI channel quality indicator (CQI) table index. There are multiple CQI tables.
      * The definition of CQI in each table is different.
      * Reference: 3GPP TS 138.214 section 5.2.2.1.
-     * Range [1, 3], INT_MAX means invalid/unreported.
+     * Range [1, 3], RadioConst:VALUE_UNAVAILABLE means invalid/unreported.
      */
     int csiCqiTableIndex;
     /**
@@ -69,14 +71,14 @@
      * index is provided for each subband, in ascending order of subband index. If CQI is not
      * available, the CQI report is empty.
      * Reference: 3GPP TS 138.214 section 5.2.2.1.
-     * Range [0, 15], 0xFF means invalid/unreported.
+     * Range [0, 15], RadioConst:VALUE_UNAVAILABLE_BYTE means invalid/unreported.
      */
     byte[] csiCqiReport;
     /**
      * Timing advance in micro seconds for a one way trip from cell to device. Approximate distance
      * is calculated using 300m/us * timingAdvance. Range: 0 to 1282 inclusive.
-     * INT_MAX: 0x7FFFFFFF denotes invalid/unreported value.
+     * RadioConst:VALUE_UNAVAILABLE denotes invalid/unreported value.
      * Reference: 3GPP 36.213 section 4.2.3
      */
-    int timingAdvance = 0x7FFFFFFF;
+    int timingAdvance = RadioConst.VALUE_UNAVAILABLE;
 }
diff --git a/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl b/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl
index 71961a3..6fe1d27 100644
--- a/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl
@@ -23,6 +23,7 @@
  */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable NrVopsInfo {
     /**
      * Emergency services not supported
diff --git a/radio/aidl/android/hardware/radio/network/PhysicalChannelConfig.aidl b/radio/aidl/android/hardware/radio/network/PhysicalChannelConfig.aidl
index ecb9463..b648ef8 100644
--- a/radio/aidl/android/hardware/radio/network/PhysicalChannelConfig.aidl
+++ b/radio/aidl/android/hardware/radio/network/PhysicalChannelConfig.aidl
@@ -27,11 +27,11 @@
     /**
      * Connection status for cell. Valid values are PRIMARY_SERVING and SECONDARY_SERVING
      */
-    CellConnectionStatus status;
+    CellConnectionStatus status = CellConnectionStatus.NONE;
     /**
      * The radio technology for this physical channel
      */
-    RadioTechnology rat;
+    RadioTechnology rat = RadioTechnology.UNKNOWN;
     /**
      * Downlink Absolute Radio Frequency Channel Number
      */
diff --git a/radio/aidl/android/hardware/radio/network/RadioAccessSpecifier.aidl b/radio/aidl/android/hardware/radio/network/RadioAccessSpecifier.aidl
index b3cee47..8bb4fe0 100644
--- a/radio/aidl/android/hardware/radio/network/RadioAccessSpecifier.aidl
+++ b/radio/aidl/android/hardware/radio/network/RadioAccessSpecifier.aidl
@@ -26,7 +26,7 @@
     /**
      * The type of network to scan.
      */
-    AccessNetwork accessNetwork;
+    AccessNetwork accessNetwork = AccessNetwork.UNKNOWN;
     /**
      * The frequency bands to scan. Maximum length of the vector is 8.
      */
diff --git a/radio/aidl/android/hardware/radio/network/RadioBandMode.aidl b/radio/aidl/android/hardware/radio/network/RadioBandMode.aidl
index 364a562..bd83b7d 100644
--- a/radio/aidl/android/hardware/radio/network/RadioBandMode.aidl
+++ b/radio/aidl/android/hardware/radio/network/RadioBandMode.aidl
@@ -20,6 +20,7 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum RadioBandMode {
     /**
      * "Unspecified" (selected by baseband automatically)
diff --git a/radio/aidl/android/hardware/radio/network/RegState.aidl b/radio/aidl/android/hardware/radio/network/RegState.aidl
index de2d5f6..15e7160 100644
--- a/radio/aidl/android/hardware/radio/network/RegState.aidl
+++ b/radio/aidl/android/hardware/radio/network/RegState.aidl
@@ -25,6 +25,7 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum RegState {
     /**
      * Not registered, MT is not currently searching for a new operator to register
diff --git a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
index 57a73c0..a7857ef 100644
--- a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
+++ b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
@@ -32,7 +32,7 @@
      * EUTRAN, NGRAN, or another technology that does not support circuit-switched services, this
      * value reports registration in the Packet-switched domain.
      */
-    RegState regState;
+    RegState regState = RegState.NOT_REG_MT_NOT_SEARCHING_OP;
     /**
      * Indicates the radio technology, which must not be UNKNOWN if regState is REG_HOME,
      * REG_ROAMING, NOT_REG_MT_NOT_SEARCHING_OP_EM, NOT_REG_MT_SEARCHING_OP_EM, REG_DENIED_EM,
@@ -40,12 +40,12 @@
      * When the device is on carrier aggregation, vendor RIL service must properly report multiple
      * PhysicalChannelConfig elements through IRadioNetwork::currentPhysicalChannelConfigs.
      */
-    RadioTechnology rat;
+    RadioTechnology rat = RadioTechnology.UNKNOWN;
     /**
      * Cause code reported by the network in case registration fails. This will be a mobility
      * management cause code defined for MM, GMM, MME or equivalent as appropriate for the RAT.
      */
-    RegistrationFailCause reasonForDenial;
+    RegistrationFailCause reasonForDenial = RegistrationFailCause.NONE;
     /**
      * CellIdentity
      */
diff --git a/radio/aidl/android/hardware/radio/network/SecurityAlgorithmUpdate.aidl b/radio/aidl/android/hardware/radio/network/SecurityAlgorithmUpdate.aidl
index e945d3b..ab48148 100644
--- a/radio/aidl/android/hardware/radio/network/SecurityAlgorithmUpdate.aidl
+++ b/radio/aidl/android/hardware/radio/network/SecurityAlgorithmUpdate.aidl
@@ -31,15 +31,15 @@
     /**
      * Type of connection event which is being reported on
      */
-    ConnectionEvent connectionEvent;
+    ConnectionEvent connectionEvent = ConnectionEvent.CS_SIGNALLING_GSM;
     /**
      * Encryption algorithm which was used
      */
-    SecurityAlgorithm encryption;
+    SecurityAlgorithm encryption = SecurityAlgorithm.A50;
     /**
      * Integrity algorithm which was used
      */
-    SecurityAlgorithm integrity;
+    SecurityAlgorithm integrity = SecurityAlgorithm.A50;
     /**
      * Whether or not this connection event is associated with an
      * unauthenticated / unencrypted emergency session
diff --git a/radio/aidl/android/hardware/radio/network/SignalStrength.aidl b/radio/aidl/android/hardware/radio/network/SignalStrength.aidl
index 5fed522..fbe3be2 100644
--- a/radio/aidl/android/hardware/radio/network/SignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/SignalStrength.aidl
@@ -30,37 +30,37 @@
 parcelable SignalStrength {
     /**
      * If GSM measurements are provided, this structure must contain valid measurements; otherwise
-     * all fields should be set to INT_MAX to mark them as invalid.
+     * all fields should be set to RadioConst:VALUE_UNAVAILABLE to mark them as invalid.
      */
     GsmSignalStrength gsm;
     /**
      * If CDMA measurements are provided, this structure must contain valid measurements; otherwise
-     * all fields should be set to INT_MAX to mark them as invalid.
+     * all fields should be set to RadioConst:VALUE_UNAVAILABLE to mark them as invalid.
      */
     CdmaSignalStrength cdma;
     /**
      * If EvDO measurements are provided, this structure must contain valid measurements; otherwise
-     * all fields should be set to INT_MAX to mark them as invalid.
+     * all fields should be set to RadioConst:VALUE_UNAVAILABLE to mark them as invalid.
      */
     EvdoSignalStrength evdo;
     /**
      * If LTE measurements are provided, this structure must contain valid measurements; otherwise
-     * all fields should be set to INT_MAX to mark them as invalid.
+     * all fields should be set to RadioConst:VALUE_UNAVAILABLE to mark them as invalid.
      */
     LteSignalStrength lte;
     /**
      * If TD-SCDMA measurements are provided, this structure must contain valid measurements;
-     * otherwise all fields should be set to INT_MAX to mark them as invalid.
+     * otherwise all fields should be set to RadioConst:VALUE_UNAVAILABLE to mark them as invalid.
      */
     TdscdmaSignalStrength tdscdma;
     /**
      * If WCDMA measurements are provided, this structure must contain valid measurements; otherwise
-     * all fields should be set to INT_MAX to mark them as invalid.
+     * all fields should be set to RadioConst:VALUE_UNAVAILABLE to mark them as invalid.
      */
     WcdmaSignalStrength wcdma;
     /**
      * If NR 5G measurements are provided, this structure must contain valid measurements; otherwise
-     * all fields should be set to INT_MAX to mark them as invalid.
+     * all fields should be set to RadioConst:VALUE_UNAVAILABLE to mark them as invalid.
      */
     NrSignalStrength nr;
 }
diff --git a/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl b/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl
index e440a64..3933889 100644
--- a/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl
@@ -24,6 +24,7 @@
  */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable SignalThresholdInfo {
     /**
      * Received Signal Strength Indication.
@@ -121,5 +122,5 @@
     /**
      * The Radio Access Network for current threshold info.
      */
-    AccessNetwork ran;
+    AccessNetwork ran = AccessNetwork.UNKNOWN;
 }
diff --git a/radio/aidl/android/hardware/radio/network/TdscdmaSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/TdscdmaSignalStrength.aidl
index 4afdd0f..87c6baa 100644
--- a/radio/aidl/android/hardware/radio/network/TdscdmaSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/TdscdmaSignalStrength.aidl
@@ -22,17 +22,17 @@
 parcelable TdscdmaSignalStrength {
     /**
      * UTRA carrier RSSI as defined in TS 25.225 5.1.4. Valid values are (0-31, 99) as defined in
-     * TS 27.007 8.5. INT_MAX denotes that the value is invalid/unreported.
+     * TS 27.007 8.5. RadioConst:VALUE_UNAVAILABLE denotes that the value is invalid/unreported.
      */
     int signalStrength;
     /**
      * Transport Channel BER as defined in TS 25.225 5.2.5. Valid values are (0-7, 99) as defined in
-     * TS 27.007 8.5. INT_MAX denotes that the value is invalid/unreported.
+     * TS 27.007 8.5. RadioConst:VALUE_UNAVAILABLE denotes that the value is invalid/unreported.
      */
     int bitErrorRate;
     /**
      * P-CCPCH RSCP as defined in TS 25.225 5.1.1. Valid values are (0-96, 255) as defined in
-     * TS 27.007 8.69. INT_MAX denotes that the value is invalid/unreported.
+     * TS 27.007 8.69. RadioConst:VALUE_UNAVAILABLE denotes that the value is invalid/unreported.
      */
     int rscp;
 }
diff --git a/radio/aidl/android/hardware/radio/network/WcdmaSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/WcdmaSignalStrength.aidl
index ace89ed..8bc7fb8 100644
--- a/radio/aidl/android/hardware/radio/network/WcdmaSignalStrength.aidl
+++ b/radio/aidl/android/hardware/radio/network/WcdmaSignalStrength.aidl
@@ -21,21 +21,23 @@
 @JavaDerive(toString=true)
 parcelable WcdmaSignalStrength {
     /**
-     * Valid values are (0-31, 99) as defined in TS 27.007 8.5; INT_MAX means unreported.
+     * Valid values are (0-31, 99) as defined in TS 27.007 8.5; RadioConst:VALUE_UNAVAILABLE means
+     * unreported.
      */
     int signalStrength;
     /**
-     * Bit error rate (0-7, 99) as defined in TS 27.007 8.5; INT_MAX means invalid/unreported.
+     * Bit error rate (0-7, 99) as defined in TS 27.007 8.5; RadioConst:VALUE_UNAVAILABLE means
+     * invalid/unreported.
      */
     int bitErrorRate;
     /**
      * CPICH RSCP as defined in TS 25.215 5.1.1. Valid values are (0-96, 255) as defined in
-     * TS 27.007 8.69. INT_MAX denotes that the value is invalid/unreported.
+     * TS 27.007 8.69. RadioConst:VALUE_UNAVAILABLE denotes that the value is invalid/unreported.
      */
     int rscp;
     /**
      * Ec/No value as defined in TS 25.215 5.1.5. Valid values are (0-49, 255) as defined in
-     * TS 27.007 8.69. INT_MAX denotes that the value is invalid/unreported.
+     * TS 27.007 8.69. RadioConst:VALUE_UNAVAILABLE denotes that the value is invalid/unreported.
      */
     int ecno;
 }
diff --git a/radio/aidl/android/hardware/radio/sim/AppStatus.aidl b/radio/aidl/android/hardware/radio/sim/AppStatus.aidl
index 7fe8e40..602c8c5 100644
--- a/radio/aidl/android/hardware/radio/sim/AppStatus.aidl
+++ b/radio/aidl/android/hardware/radio/sim/AppStatus.aidl
@@ -22,6 +22,7 @@
 /** @hide */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable AppStatus {
     const int APP_STATE_UNKNOWN = 0;
     const int APP_STATE_DETECTED = 1;
@@ -57,7 +58,7 @@
     /**
      * Applicable only if appState == SUBSCRIPTION_PERSO
      */
-    PersoSubstate persoSubstate;
+    PersoSubstate persoSubstate = PersoSubstate.UNKNOWN;
     /**
      * e.g., from 0xA0, 0x00 -> 0x41, 0x30, 0x30, 0x30
      */
@@ -67,6 +68,6 @@
      * Applicable to USIM, CSIM and ISIM
      */
     boolean pin1Replaced;
-    PinState pin1;
-    PinState pin2;
+    PinState pin1 = PinState.UNKNOWN;
+    PinState pin2 = PinState.UNKNOWN;
 }
diff --git a/radio/aidl/android/hardware/radio/sim/CardPowerState.aidl b/radio/aidl/android/hardware/radio/sim/CardPowerState.aidl
index 2598dcb..0d5db2a 100644
--- a/radio/aidl/android/hardware/radio/sim/CardPowerState.aidl
+++ b/radio/aidl/android/hardware/radio/sim/CardPowerState.aidl
@@ -20,6 +20,7 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum CardPowerState {
     POWER_DOWN,
     POWER_UP,
diff --git a/radio/aidl/android/hardware/radio/sim/CardStatus.aidl b/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
index 043bfa4..90aa8e0 100644
--- a/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
+++ b/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
@@ -48,7 +48,7 @@
     /**
      * Applicable to USIM and CSIM
      */
-    PinState universalPinState;
+    PinState universalPinState = PinState.UNKNOWN;
     /**
      * Value < RadioConst:CARD_MAX_APPS, -1 if none
      */
diff --git a/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl b/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
index 0002d5a..69c618f 100644
--- a/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
+++ b/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
@@ -61,7 +61,7 @@
      */
     boolean allowedCarriersPrioritized;
     /** Current restriction status as defined in CarrierRestrictionStatus enum */
-    CarrierRestrictionStatus status;
+    CarrierRestrictionStatus status = CarrierRestrictionStatus.UNKNOWN;
 
     /**  Allowed carriers. */
     CarrierInfo[] allowedCarrierInfoList = {};
@@ -71,5 +71,5 @@
      * excludedCarriers has same mcc/mnc and gid1 is ABCD. It means except the carrier whose gid1
      * is ABCD, all carriers with the same mcc/mnc are allowed.
      */
-    CarrierInfo[]  excludedCarrierInfoList = {};
-}
\ No newline at end of file
+    CarrierInfo[] excludedCarrierInfoList = {};
+}
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
index 7870a74..1e010b9 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
@@ -257,7 +257,7 @@
      * Request APDU exchange on the basic channel. This command reflects TS 27.007
      * "generic SIM access" operation (+CSIM). The modem must ensure proper function of GSM/CDMA,
      * and filter commands appropriately. It must filter channel management and SELECT by DF
-     * name commands. "sessionid" field must be ignored.
+     * name commands. "sessionId" field is always 0 (for aid="") and may be ignored.
      *
      * @param serial Serial number of request.
      * @param message SimApdu to be sent
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
index 91b5729..cf08bad 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
@@ -263,6 +263,8 @@
      *   RadioError:NONE
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS when given channel is invalid or basic (channel 0)
+     *   RadioError:MISSING_RESOURCE when given channel is not open
      *   RadioError:NO_MEMORY
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
@@ -325,6 +327,7 @@
      *   RadioError:NONE
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
      *   RadioError:NO_MEMORY
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
diff --git a/radio/aidl/android/hardware/radio/sim/PbReceivedStatus.aidl b/radio/aidl/android/hardware/radio/sim/PbReceivedStatus.aidl
index f9414a8..c75a4ef 100644
--- a/radio/aidl/android/hardware/radio/sim/PbReceivedStatus.aidl
+++ b/radio/aidl/android/hardware/radio/sim/PbReceivedStatus.aidl
@@ -23,6 +23,7 @@
 @VintfStability
 @Backing(type="byte")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum PbReceivedStatus {
     /**
      * Indicates that retrieval is fine.
diff --git a/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl b/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
index 89d85a9..7ec5141 100644
--- a/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
+++ b/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
@@ -20,6 +20,7 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum SimLockMultiSimPolicy {
 
     /**
diff --git a/radio/aidl/android/hardware/radio/sim/SimRefreshResult.aidl b/radio/aidl/android/hardware/radio/sim/SimRefreshResult.aidl
index 943f1d2..618ac32 100644
--- a/radio/aidl/android/hardware/radio/sim/SimRefreshResult.aidl
+++ b/radio/aidl/android/hardware/radio/sim/SimRefreshResult.aidl
@@ -19,6 +19,7 @@
 /** @hide */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable SimRefreshResult {
     /**
      * A file on SIM has been updated.
diff --git a/radio/aidl/android/hardware/radio/voice/Call.aidl b/radio/aidl/android/hardware/radio/voice/Call.aidl
index ee0b025..9990f28 100644
--- a/radio/aidl/android/hardware/radio/voice/Call.aidl
+++ b/radio/aidl/android/hardware/radio/voice/Call.aidl
@@ -99,7 +99,7 @@
      * Vector of User-User Signaling Information
      */
     UusInfo[] uusInfo;
-    AudioQuality audioQuality;
+    AudioQuality audioQuality = AudioQuality.UNSPECIFIED;
     /**
      * Forwarded number. It can set only one forwarded number based on 3GPP rule of the CS.
      * Reference: 3GPP TS 24.008 section 10.5.4.21b
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
index 7e5a68d..90b2715 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
@@ -26,6 +26,7 @@
  */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable CdmaDisplayInfoRecord {
     const int CDMA_ALPHA_INFO_BUFFER_LENGTH = 64;
     /**
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl
index f5c656b..19903c6 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl
@@ -30,6 +30,7 @@
  */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable CdmaInformationRecord {
     const int CDMA_MAX_NUMBER_OF_INFO_RECS = 10;
     /**
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
index b04e273..3a00cae 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
@@ -24,6 +24,7 @@
  */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable CdmaNumberInfoRecord {
     const int CDMA_NUMBER_INFO_BUFFER_LENGTH = 81;
     /**
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
index 691712e..cb30da8 100644
--- a/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
+++ b/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
@@ -21,6 +21,7 @@
 /** @hide */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable CdmaRedirectingNumberInfoRecord {
     /**
      * Redirecting Number Information Record as defined in C.S0005 section 3.7.5.11
diff --git a/radio/aidl/android/hardware/radio/voice/ClipStatus.aidl b/radio/aidl/android/hardware/radio/voice/ClipStatus.aidl
index 0a2ea2c..070aff7 100644
--- a/radio/aidl/android/hardware/radio/voice/ClipStatus.aidl
+++ b/radio/aidl/android/hardware/radio/voice/ClipStatus.aidl
@@ -20,6 +20,7 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum ClipStatus {
     /**
      * CLIP provisioned
diff --git a/radio/aidl/android/hardware/radio/voice/EmergencyCallRouting.aidl b/radio/aidl/android/hardware/radio/voice/EmergencyCallRouting.aidl
index 9f8993d..36e0bc0 100644
--- a/radio/aidl/android/hardware/radio/voice/EmergencyCallRouting.aidl
+++ b/radio/aidl/android/hardware/radio/voice/EmergencyCallRouting.aidl
@@ -23,6 +23,7 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum EmergencyCallRouting {
     /**
      * Indicates Android does not require how to handle the corresponding emergency call; it is
diff --git a/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl b/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl
index 9a38197..7737e94 100644
--- a/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl
+++ b/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl
@@ -20,7 +20,10 @@
 @VintfStability
 @Backing(type="int")
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 enum LastCallFailCause {
+    /** Do not use. */
+    INVALID = 0,
     UNOBTAINABLE_NUMBER = 1,
     NO_ROUTE_TO_DESTINATION = 3,
     CHANNEL_UNACCEPTABLE = 6,
diff --git a/radio/aidl/android/hardware/radio/voice/LastCallFailCauseInfo.aidl b/radio/aidl/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
index 4ed17d2..6af38bb 100644
--- a/radio/aidl/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
+++ b/radio/aidl/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
@@ -22,6 +22,6 @@
 @VintfStability
 @JavaDerive(toString=true)
 parcelable LastCallFailCauseInfo {
-    LastCallFailCause causeCode;
+    LastCallFailCause causeCode = LastCallFailCause.INVALID;
     String vendorCause;
 }
diff --git a/radio/aidl/android/hardware/radio/voice/SsInfoData.aidl b/radio/aidl/android/hardware/radio/voice/SsInfoData.aidl
index c965a7d..9c9dcff 100644
--- a/radio/aidl/android/hardware/radio/voice/SsInfoData.aidl
+++ b/radio/aidl/android/hardware/radio/voice/SsInfoData.aidl
@@ -19,6 +19,7 @@
 /** @hide */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable SsInfoData {
     const int SS_INFO_MAX = 4;
     /**
diff --git a/radio/aidl/android/hardware/radio/voice/StkCcUnsolSsResult.aidl b/radio/aidl/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
index 9fe4024..641994e 100644
--- a/radio/aidl/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
+++ b/radio/aidl/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
@@ -84,7 +84,7 @@
      * Values are a bitfield of SUPP_SERVICE_CLASS_
      */
     int serviceClass;
-    RadioError result;
+    RadioError result = RadioError.NONE;
     /**
      * Valid only for all serviceType except SERVICE_TYPE_CF_* else empty.
      * Only one of ssInfo and cfData may contain values and the other must be empty.
diff --git a/radio/aidl/android/hardware/radio/voice/UusInfo.aidl b/radio/aidl/android/hardware/radio/voice/UusInfo.aidl
index 5d499ca..3760ac6 100644
--- a/radio/aidl/android/hardware/radio/voice/UusInfo.aidl
+++ b/radio/aidl/android/hardware/radio/voice/UusInfo.aidl
@@ -22,6 +22,7 @@
  */
 @VintfStability
 @JavaDerive(toString=true)
+@SuppressWarnings(value={"redundant-name"})
 parcelable UusInfo {
     /**
      * User specified protocol
diff --git a/radio/aidl/compat/libradiocompat/Android.bp b/radio/aidl/compat/libradiocompat/Android.bp
index d78455e..a3a8c20 100644
--- a/radio/aidl/compat/libradiocompat/Android.bp
+++ b/radio/aidl/compat/libradiocompat/Android.bp
@@ -22,8 +22,25 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+cc_defaults {
+    name: "android.hardware.radio-library.aidl_deps",
+    shared_libs: [
+        "android.hardware.radio.config-V4-ndk",
+        "android.hardware.radio.data-V4-ndk",
+        "android.hardware.radio.ims-V3-ndk",
+        "android.hardware.radio.ims.media-V3-ndk",
+        "android.hardware.radio.messaging-V4-ndk",
+        "android.hardware.radio.modem-V4-ndk",
+        "android.hardware.radio.network-V4-ndk",
+        "android.hardware.radio.sap-V1-ndk",
+        "android.hardware.radio.sim-V4-ndk",
+        "android.hardware.radio.voice-V4-ndk",
+    ],
+}
+
 cc_library {
     name: "android.hardware.radio-library.compat",
+    defaults: ["android.hardware.radio-library.aidl_deps"],
     relative_install_path: "hw",
     vendor: true,
     cflags: [
@@ -32,20 +49,10 @@
         "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
     ],
     shared_libs: [
-        "android.hardware.radio.config-V3-ndk",
         "android.hardware.radio.config@1.0",
         "android.hardware.radio.config@1.1",
         "android.hardware.radio.config@1.2",
         "android.hardware.radio.config@1.3",
-        "android.hardware.radio.data-V3-ndk",
-        "android.hardware.radio.ims-V2-ndk",
-        "android.hardware.radio.ims.media-V2-ndk",
-        "android.hardware.radio.messaging-V3-ndk",
-        "android.hardware.radio.modem-V3-ndk",
-        "android.hardware.radio.network-V3-ndk",
-        "android.hardware.radio.sap-V1-ndk",
-        "android.hardware.radio.sim-V3-ndk",
-        "android.hardware.radio.voice-V3-ndk",
         "android.hardware.radio@1.0",
         "android.hardware.radio@1.1",
         "android.hardware.radio@1.2",
diff --git a/radio/aidl/compat/service/Android.bp b/radio/aidl/compat/service/Android.bp
index c8bbd4c..3d46d4f 100644
--- a/radio/aidl/compat/service/Android.bp
+++ b/radio/aidl/compat/service/Android.bp
@@ -24,6 +24,7 @@
 
 cc_binary {
     name: "android.hardware.radio-service.compat",
+    defaults: ["android.hardware.radio-library.aidl_deps"],
     relative_install_path: "hw",
     init_rc: ["radio-compat.rc"],
     vintf_fragments: ["radio-compat.xml"],
@@ -35,20 +36,10 @@
     ],
     shared_libs: [
         "android.hardware.radio-library.compat",
-        "android.hardware.radio.config-V3-ndk",
         "android.hardware.radio.config@1.0",
         "android.hardware.radio.config@1.1",
         "android.hardware.radio.config@1.2",
         "android.hardware.radio.config@1.3",
-        "android.hardware.radio.data-V3-ndk",
-        "android.hardware.radio.ims-V2-ndk",
-        "android.hardware.radio.ims.media-V2-ndk",
-        "android.hardware.radio.messaging-V3-ndk",
-        "android.hardware.radio.modem-V3-ndk",
-        "android.hardware.radio.network-V3-ndk",
-        "android.hardware.radio.sap-V1-ndk",
-        "android.hardware.radio.sim-V3-ndk",
-        "android.hardware.radio.voice-V3-ndk",
         "android.hardware.radio@1.0",
         "android.hardware.radio@1.1",
         "android.hardware.radio@1.2",
diff --git a/radio/aidl/vts/Android.bp b/radio/aidl/vts/Android.bp
index e83a7c1..6e8ce8b 100644
--- a/radio/aidl/vts/Android.bp
+++ b/radio/aidl/vts/Android.bp
@@ -25,6 +25,7 @@
 cc_test {
     name: "VtsHalRadioTargetTest",
     defaults: [
+        "aconfig_lib_cc_shared_link.defaults",
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
@@ -76,17 +77,17 @@
         "server_configurable_flags",
     ],
     static_libs: [
-        "android.hardware.radio-V3-ndk",
-        "android.hardware.radio.config-V3-ndk",
-        "android.hardware.radio.data-V3-ndk",
-        "android.hardware.radio.ims-V2-ndk",
-        "android.hardware.radio.ims.media-V2-ndk",
-        "android.hardware.radio.messaging-V3-ndk",
-        "android.hardware.radio.modem-V3-ndk",
-        "android.hardware.radio.network-V3-ndk",
+        "android.hardware.radio-V4-ndk",
+        "android.hardware.radio.config-V4-ndk",
+        "android.hardware.radio.data-V4-ndk",
+        "android.hardware.radio.ims-V3-ndk",
+        "android.hardware.radio.ims.media-V3-ndk",
+        "android.hardware.radio.messaging-V4-ndk",
+        "android.hardware.radio.modem-V4-ndk",
+        "android.hardware.radio.network-V4-ndk",
         "android.hardware.radio.sap-V1-ndk",
-        "android.hardware.radio.sim-V3-ndk",
-        "android.hardware.radio.voice-V3-ndk",
+        "android.hardware.radio.sim-V4-ndk",
+        "android.hardware.radio.voice-V4-ndk",
         "telephony_flags_c_lib",
     ],
     test_suites: [
diff --git a/radio/aidl/vts/radio_sim_test.cpp b/radio/aidl/vts/radio_sim_test.cpp
index ec1facc..2823977 100644
--- a/radio/aidl/vts/radio_sim_test.cpp
+++ b/radio/aidl/vts/radio_sim_test.cpp
@@ -533,7 +533,7 @@
         EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
 
         if (aidl_version <= 2) {
-            EXPECT_EQ(1, radioRsp_sim->carrierRestrictionsResp.allowedCarriers.size());
+            ASSERT_EQ(1, radioRsp_sim->carrierRestrictionsResp.allowedCarriers.size());
             EXPECT_EQ(0, radioRsp_sim->carrierRestrictionsResp.excludedCarriers.size());
 
             ASSERT_TRUE(std::string("123") ==
@@ -545,7 +545,7 @@
             ASSERT_TRUE(radioRsp_sim->carrierRestrictionsResp.allowedCarriersPrioritized);
             EXPECT_EQ(SimLockMultiSimPolicy::NO_MULTISIM_POLICY, radioRsp_sim->multiSimPolicyResp);
         } else {
-            EXPECT_EQ(1, radioRsp_sim->carrierRestrictionsResp.allowedCarrierInfoList.size());
+            ASSERT_EQ(1, radioRsp_sim->carrierRestrictionsResp.allowedCarrierInfoList.size());
             EXPECT_EQ(0, radioRsp_sim->carrierRestrictionsResp.excludedCarrierInfoList.size());
             ASSERT_EQ(std::string("123"),
                       radioRsp_sim->carrierRestrictionsResp.allowedCarrierInfoList[0].mcc);
diff --git a/rebootescrow/aidl/Android.bp b/rebootescrow/aidl/Android.bp
index 39aaa07..3d5b827 100644
--- a/rebootescrow/aidl/Android.bp
+++ b/rebootescrow/aidl/Android.bp
@@ -10,6 +10,7 @@
 aidl_interface {
     name: "android.hardware.rebootescrow",
     vendor_available: true,
+    frozen: true,
     srcs: [
         "android/hardware/rebootescrow/IRebootEscrow.aidl",
     ],
diff --git a/rebootescrow/aidl/vts/functional/Android.bp b/rebootescrow/aidl/vts/functional/Android.bp
index 76b6784..ba15cca 100644
--- a/rebootescrow/aidl/vts/functional/Android.bp
+++ b/rebootescrow/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_platform_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/renderscript/1.0/vts/functional/Android.bp b/renderscript/1.0/vts/functional/Android.bp
index 4b665b1..64c4aab 100644
--- a/renderscript/1.0/vts/functional/Android.bp
+++ b/renderscript/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_renderscript_nnapi",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/secure_element/1.0/vts/functional/Android.bp b/secure_element/1.0/vts/functional/Android.bp
index 735d7c9..25ce050 100644
--- a/secure_element/1.0/vts/functional/Android.bp
+++ b/secure_element/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_pixel_connectivity_nfc",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/secure_element/1.1/vts/functional/Android.bp b/secure_element/1.1/vts/functional/Android.bp
index d63e7c4..ad7f97c 100644
--- a/secure_element/1.1/vts/functional/Android.bp
+++ b/secure_element/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_pixel_connectivity_nfc",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/secure_element/1.2/vts/functional/Android.bp b/secure_element/1.2/vts/functional/Android.bp
index 63a0a19..5a01851 100644
--- a/secure_element/1.2/vts/functional/Android.bp
+++ b/secure_element/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_pixel_connectivity_nfc",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/secure_element/aidl/Android.bp b/secure_element/aidl/Android.bp
index 655487d..1145305 100644
--- a/secure_element/aidl/Android.bp
+++ b/secure_element/aidl/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_pixel_connectivity_nfc",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/secure_element/aidl/default/Android.bp b/secure_element/aidl/default/Android.bp
index b382822..6f5e5f7 100644
--- a/secure_element/aidl/default/Android.bp
+++ b/secure_element/aidl/default/Android.bp
@@ -55,6 +55,7 @@
     prebuilts: [
         "secure_element.rc",
         "secure_element.xml",
-        "android.hardware.se.omapi.ese.prebuilt.xml", // <feature>
+        // TODO (b/289193458): Add this back when access control is implemented for cuttlefish.
+        // "android.hardware.se.omapi.ese.prebuilt.xml", // <feature>
     ],
 }
diff --git a/security/authgraph/aidl/vts/functional/Android.bp b/security/authgraph/aidl/vts/functional/Android.bp
index 28a70e2..e40525c 100644
--- a/security/authgraph/aidl/vts/functional/Android.bp
+++ b/security/authgraph/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/security/keymint/aidl/Android.bp b/security/keymint/aidl/Android.bp
index e346610..76aa604 100644
--- a/security/keymint/aidl/Android.bp
+++ b/security/keymint/aidl/Android.bp
@@ -17,7 +17,7 @@
         "android.hardware.security.secureclock-V1",
     ],
     stability: "vintf",
-    frozen: true,
+    frozen: false,
     backend: {
         java: {
             platform_apis: true,
@@ -51,34 +51,42 @@
 
 }
 
+// An aidl_interface_defaults that includes the latest KeyMint AIDL interface.
+// aidl_interface modules that depend on KeyMint directly can include this
+// aidl_interface_defaults to avoid managing dependency versions explicitly.
+aidl_interface_defaults {
+    name: "android.hardware.security.keymint-latest-defaults",
+    imports: ["android.hardware.security.keymint-V4"],
+}
+
 // cc_defaults that includes the latest KeyMint AIDL library.
 // Modules that depend on KeyMint directly can include this cc_defaults to avoid
 // managing dependency versions explicitly.
 cc_defaults {
     name: "keymint_use_latest_hal_aidl_ndk_static",
     static_libs: [
-        "android.hardware.security.keymint-V3-ndk",
+        "android.hardware.security.keymint-V4-ndk",
     ],
 }
 
 cc_defaults {
     name: "keymint_use_latest_hal_aidl_ndk_shared",
     shared_libs: [
-        "android.hardware.security.keymint-V3-ndk",
+        "android.hardware.security.keymint-V4-ndk",
     ],
 }
 
 cc_defaults {
     name: "keymint_use_latest_hal_aidl_cpp_static",
     static_libs: [
-        "android.hardware.security.keymint-V3-cpp",
+        "android.hardware.security.keymint-V4-cpp",
     ],
 }
 
 cc_defaults {
     name: "keymint_use_latest_hal_aidl_cpp_shared",
     shared_libs: [
-        "android.hardware.security.keymint-V3-cpp",
+        "android.hardware.security.keymint-V4-cpp",
     ],
 }
 
@@ -88,6 +96,16 @@
 rust_defaults {
     name: "keymint_use_latest_hal_aidl_rust",
     rustlibs: [
-        "android.hardware.security.keymint-V3-rust",
+        "android.hardware.security.keymint-V4-rust",
+    ],
+}
+
+// java_defaults that includes the latest KeyMint AIDL library.
+// Modules that depend on KeyMint directly can include this java_defaults to avoid
+// managing dependency versions explicitly.
+java_defaults {
+    name: "keymint_use_latest_hal_aidl_java",
+    static_libs: [
+        "android.hardware.security.keymint-V4-java",
     ],
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
index b05a0f3..71d3651 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
@@ -36,90 +36,91 @@
 @Backing(type="int") @VintfStability
 enum ErrorCode {
   OK = 0,
-  ROOT_OF_TRUST_ALREADY_SET = -1,
-  UNSUPPORTED_PURPOSE = -2,
-  INCOMPATIBLE_PURPOSE = -3,
-  UNSUPPORTED_ALGORITHM = -4,
-  INCOMPATIBLE_ALGORITHM = -5,
-  UNSUPPORTED_KEY_SIZE = -6,
-  UNSUPPORTED_BLOCK_MODE = -7,
-  INCOMPATIBLE_BLOCK_MODE = -8,
-  UNSUPPORTED_MAC_LENGTH = -9,
-  UNSUPPORTED_PADDING_MODE = -10,
-  INCOMPATIBLE_PADDING_MODE = -11,
-  UNSUPPORTED_DIGEST = -12,
-  INCOMPATIBLE_DIGEST = -13,
-  INVALID_EXPIRATION_TIME = -14,
-  INVALID_USER_ID = -15,
-  INVALID_AUTHORIZATION_TIMEOUT = -16,
-  UNSUPPORTED_KEY_FORMAT = -17,
-  INCOMPATIBLE_KEY_FORMAT = -18,
-  UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19,
-  UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20,
-  INVALID_INPUT_LENGTH = -21,
-  KEY_EXPORT_OPTIONS_INVALID = -22,
-  DELEGATION_NOT_ALLOWED = -23,
-  KEY_NOT_YET_VALID = -24,
-  KEY_EXPIRED = -25,
-  KEY_USER_NOT_AUTHENTICATED = -26,
-  OUTPUT_PARAMETER_NULL = -27,
-  INVALID_OPERATION_HANDLE = -28,
-  INSUFFICIENT_BUFFER_SPACE = -29,
-  VERIFICATION_FAILED = -30,
-  TOO_MANY_OPERATIONS = -31,
-  UNEXPECTED_NULL_POINTER = -32,
-  INVALID_KEY_BLOB = -33,
-  IMPORTED_KEY_NOT_ENCRYPTED = -34,
-  IMPORTED_KEY_DECRYPTION_FAILED = -35,
-  IMPORTED_KEY_NOT_SIGNED = -36,
-  IMPORTED_KEY_VERIFICATION_FAILED = -37,
-  INVALID_ARGUMENT = -38,
-  UNSUPPORTED_TAG = -39,
-  INVALID_TAG = -40,
-  MEMORY_ALLOCATION_FAILED = -41,
-  IMPORT_PARAMETER_MISMATCH = -44,
-  SECURE_HW_ACCESS_DENIED = -45,
-  OPERATION_CANCELLED = -46,
-  CONCURRENT_ACCESS_CONFLICT = -47,
-  SECURE_HW_BUSY = -48,
-  SECURE_HW_COMMUNICATION_FAILED = -49,
-  UNSUPPORTED_EC_FIELD = -50,
-  MISSING_NONCE = -51,
-  INVALID_NONCE = -52,
-  MISSING_MAC_LENGTH = -53,
-  KEY_RATE_LIMIT_EXCEEDED = -54,
-  CALLER_NONCE_PROHIBITED = -55,
-  KEY_MAX_OPS_EXCEEDED = -56,
-  INVALID_MAC_LENGTH = -57,
-  MISSING_MIN_MAC_LENGTH = -58,
-  UNSUPPORTED_MIN_MAC_LENGTH = -59,
-  UNSUPPORTED_KDF = -60,
-  UNSUPPORTED_EC_CURVE = -61,
-  KEY_REQUIRES_UPGRADE = -62,
-  ATTESTATION_CHALLENGE_MISSING = -63,
-  KEYMINT_NOT_CONFIGURED = -64,
-  ATTESTATION_APPLICATION_ID_MISSING = -65,
-  CANNOT_ATTEST_IDS = -66,
-  ROLLBACK_RESISTANCE_UNAVAILABLE = -67,
-  HARDWARE_TYPE_UNAVAILABLE = -68,
-  PROOF_OF_PRESENCE_REQUIRED = -69,
-  CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = -70,
-  NO_USER_CONFIRMATION = -71,
-  DEVICE_LOCKED = -72,
-  EARLY_BOOT_ENDED = -73,
-  ATTESTATION_KEYS_NOT_PROVISIONED = -74,
-  ATTESTATION_IDS_NOT_PROVISIONED = -75,
-  INVALID_OPERATION = -76,
-  STORAGE_KEY_UNSUPPORTED = -77,
-  INCOMPATIBLE_MGF_DIGEST = -78,
-  UNSUPPORTED_MGF_DIGEST = -79,
-  MISSING_NOT_BEFORE = -80,
-  MISSING_NOT_AFTER = -81,
-  MISSING_ISSUER_SUBJECT = -82,
-  INVALID_ISSUER_SUBJECT = -83,
-  BOOT_LEVEL_EXCEEDED = -84,
-  HARDWARE_NOT_YET_AVAILABLE = -85,
-  UNIMPLEMENTED = -100,
-  VERSION_MISMATCH = -101,
-  UNKNOWN_ERROR = -1000,
+  ROOT_OF_TRUST_ALREADY_SET = (-1) /* -1 */,
+  UNSUPPORTED_PURPOSE = (-2) /* -2 */,
+  INCOMPATIBLE_PURPOSE = (-3) /* -3 */,
+  UNSUPPORTED_ALGORITHM = (-4) /* -4 */,
+  INCOMPATIBLE_ALGORITHM = (-5) /* -5 */,
+  UNSUPPORTED_KEY_SIZE = (-6) /* -6 */,
+  UNSUPPORTED_BLOCK_MODE = (-7) /* -7 */,
+  INCOMPATIBLE_BLOCK_MODE = (-8) /* -8 */,
+  UNSUPPORTED_MAC_LENGTH = (-9) /* -9 */,
+  UNSUPPORTED_PADDING_MODE = (-10) /* -10 */,
+  INCOMPATIBLE_PADDING_MODE = (-11) /* -11 */,
+  UNSUPPORTED_DIGEST = (-12) /* -12 */,
+  INCOMPATIBLE_DIGEST = (-13) /* -13 */,
+  INVALID_EXPIRATION_TIME = (-14) /* -14 */,
+  INVALID_USER_ID = (-15) /* -15 */,
+  INVALID_AUTHORIZATION_TIMEOUT = (-16) /* -16 */,
+  UNSUPPORTED_KEY_FORMAT = (-17) /* -17 */,
+  INCOMPATIBLE_KEY_FORMAT = (-18) /* -18 */,
+  UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = (-19) /* -19 */,
+  UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = (-20) /* -20 */,
+  INVALID_INPUT_LENGTH = (-21) /* -21 */,
+  KEY_EXPORT_OPTIONS_INVALID = (-22) /* -22 */,
+  DELEGATION_NOT_ALLOWED = (-23) /* -23 */,
+  KEY_NOT_YET_VALID = (-24) /* -24 */,
+  KEY_EXPIRED = (-25) /* -25 */,
+  KEY_USER_NOT_AUTHENTICATED = (-26) /* -26 */,
+  OUTPUT_PARAMETER_NULL = (-27) /* -27 */,
+  INVALID_OPERATION_HANDLE = (-28) /* -28 */,
+  INSUFFICIENT_BUFFER_SPACE = (-29) /* -29 */,
+  VERIFICATION_FAILED = (-30) /* -30 */,
+  TOO_MANY_OPERATIONS = (-31) /* -31 */,
+  UNEXPECTED_NULL_POINTER = (-32) /* -32 */,
+  INVALID_KEY_BLOB = (-33) /* -33 */,
+  IMPORTED_KEY_NOT_ENCRYPTED = (-34) /* -34 */,
+  IMPORTED_KEY_DECRYPTION_FAILED = (-35) /* -35 */,
+  IMPORTED_KEY_NOT_SIGNED = (-36) /* -36 */,
+  IMPORTED_KEY_VERIFICATION_FAILED = (-37) /* -37 */,
+  INVALID_ARGUMENT = (-38) /* -38 */,
+  UNSUPPORTED_TAG = (-39) /* -39 */,
+  INVALID_TAG = (-40) /* -40 */,
+  MEMORY_ALLOCATION_FAILED = (-41) /* -41 */,
+  IMPORT_PARAMETER_MISMATCH = (-44) /* -44 */,
+  SECURE_HW_ACCESS_DENIED = (-45) /* -45 */,
+  OPERATION_CANCELLED = (-46) /* -46 */,
+  CONCURRENT_ACCESS_CONFLICT = (-47) /* -47 */,
+  SECURE_HW_BUSY = (-48) /* -48 */,
+  SECURE_HW_COMMUNICATION_FAILED = (-49) /* -49 */,
+  UNSUPPORTED_EC_FIELD = (-50) /* -50 */,
+  MISSING_NONCE = (-51) /* -51 */,
+  INVALID_NONCE = (-52) /* -52 */,
+  MISSING_MAC_LENGTH = (-53) /* -53 */,
+  KEY_RATE_LIMIT_EXCEEDED = (-54) /* -54 */,
+  CALLER_NONCE_PROHIBITED = (-55) /* -55 */,
+  KEY_MAX_OPS_EXCEEDED = (-56) /* -56 */,
+  INVALID_MAC_LENGTH = (-57) /* -57 */,
+  MISSING_MIN_MAC_LENGTH = (-58) /* -58 */,
+  UNSUPPORTED_MIN_MAC_LENGTH = (-59) /* -59 */,
+  UNSUPPORTED_KDF = (-60) /* -60 */,
+  UNSUPPORTED_EC_CURVE = (-61) /* -61 */,
+  KEY_REQUIRES_UPGRADE = (-62) /* -62 */,
+  ATTESTATION_CHALLENGE_MISSING = (-63) /* -63 */,
+  KEYMINT_NOT_CONFIGURED = (-64) /* -64 */,
+  ATTESTATION_APPLICATION_ID_MISSING = (-65) /* -65 */,
+  CANNOT_ATTEST_IDS = (-66) /* -66 */,
+  ROLLBACK_RESISTANCE_UNAVAILABLE = (-67) /* -67 */,
+  HARDWARE_TYPE_UNAVAILABLE = (-68) /* -68 */,
+  PROOF_OF_PRESENCE_REQUIRED = (-69) /* -69 */,
+  CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = (-70) /* -70 */,
+  NO_USER_CONFIRMATION = (-71) /* -71 */,
+  DEVICE_LOCKED = (-72) /* -72 */,
+  EARLY_BOOT_ENDED = (-73) /* -73 */,
+  ATTESTATION_KEYS_NOT_PROVISIONED = (-74) /* -74 */,
+  ATTESTATION_IDS_NOT_PROVISIONED = (-75) /* -75 */,
+  INVALID_OPERATION = (-76) /* -76 */,
+  STORAGE_KEY_UNSUPPORTED = (-77) /* -77 */,
+  INCOMPATIBLE_MGF_DIGEST = (-78) /* -78 */,
+  UNSUPPORTED_MGF_DIGEST = (-79) /* -79 */,
+  MISSING_NOT_BEFORE = (-80) /* -80 */,
+  MISSING_NOT_AFTER = (-81) /* -81 */,
+  MISSING_ISSUER_SUBJECT = (-82) /* -82 */,
+  INVALID_ISSUER_SUBJECT = (-83) /* -83 */,
+  BOOT_LEVEL_EXCEEDED = (-84) /* -84 */,
+  HARDWARE_NOT_YET_AVAILABLE = (-85) /* -85 */,
+  MODULE_HASH_ALREADY_SET = (-86) /* -86 */,
+  UNIMPLEMENTED = (-100) /* -100 */,
+  VERSION_MISMATCH = (-101) /* -101 */,
+  UNKNOWN_ERROR = (-1000) /* -1000 */,
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
index dfc98f0..eb4f621 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
@@ -36,7 +36,7 @@
 @Backing(type="int") @VintfStability
 enum HardwareAuthenticatorType {
   NONE = 0,
-  PASSWORD = 1,
-  FINGERPRINT = 2,
-  ANY = -1,
+  PASSWORD = (1 << 0) /* 1 */,
+  FINGERPRINT = (1 << 1) /* 2 */,
+  ANY = 0xFFFFFFFF,
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
index dcc22c4..e6d2fdf 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -45,6 +45,9 @@
   void deleteAllKeys();
   void destroyAttestationIds();
   android.hardware.security.keymint.BeginResult begin(in android.hardware.security.keymint.KeyPurpose purpose, in byte[] keyBlob, in android.hardware.security.keymint.KeyParameter[] params, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken);
+  /**
+   * @deprecated Method has never been used due to design limitations
+   */
   void deviceLocked(in boolean passwordOnly, in @nullable android.hardware.security.secureclock.TimeStampToken timestampToken);
   void earlyBootEnded();
   byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob);
@@ -52,5 +55,6 @@
   byte[16] getRootOfTrustChallenge();
   byte[] getRootOfTrust(in byte[16] challenge);
   void sendRootOfTrust(in byte[] rootOfTrust);
+  void setAdditionalAttestationInfo(in android.hardware.security.keymint.KeyParameter[] info);
   const int AUTH_TOKEN_MAC_LENGTH = 32;
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
index 6ae2369..79341ee 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
@@ -36,69 +36,70 @@
 @Backing(type="int") @VintfStability
 enum Tag {
   INVALID = 0,
-  PURPOSE = 536870913,
-  ALGORITHM = 268435458,
-  KEY_SIZE = 805306371,
-  BLOCK_MODE = 536870916,
-  DIGEST = 536870917,
-  PADDING = 536870918,
-  CALLER_NONCE = 1879048199,
-  MIN_MAC_LENGTH = 805306376,
-  EC_CURVE = 268435466,
-  RSA_PUBLIC_EXPONENT = 1342177480,
-  INCLUDE_UNIQUE_ID = 1879048394,
-  RSA_OAEP_MGF_DIGEST = 536871115,
-  BOOTLOADER_ONLY = 1879048494,
-  ROLLBACK_RESISTANCE = 1879048495,
-  HARDWARE_TYPE = 268435760,
-  EARLY_BOOT_ONLY = 1879048497,
-  ACTIVE_DATETIME = 1610613136,
-  ORIGINATION_EXPIRE_DATETIME = 1610613137,
-  USAGE_EXPIRE_DATETIME = 1610613138,
-  MIN_SECONDS_BETWEEN_OPS = 805306771,
-  MAX_USES_PER_BOOT = 805306772,
-  USAGE_COUNT_LIMIT = 805306773,
-  USER_ID = 805306869,
-  USER_SECURE_ID = -1610612234,
-  NO_AUTH_REQUIRED = 1879048695,
-  USER_AUTH_TYPE = 268435960,
-  AUTH_TIMEOUT = 805306873,
-  ALLOW_WHILE_ON_BODY = 1879048698,
-  TRUSTED_USER_PRESENCE_REQUIRED = 1879048699,
-  TRUSTED_CONFIRMATION_REQUIRED = 1879048700,
-  UNLOCKED_DEVICE_REQUIRED = 1879048701,
-  APPLICATION_ID = -1879047591,
-  APPLICATION_DATA = -1879047492,
-  CREATION_DATETIME = 1610613437,
-  ORIGIN = 268436158,
-  ROOT_OF_TRUST = -1879047488,
-  OS_VERSION = 805307073,
-  OS_PATCHLEVEL = 805307074,
-  UNIQUE_ID = -1879047485,
-  ATTESTATION_CHALLENGE = -1879047484,
-  ATTESTATION_APPLICATION_ID = -1879047483,
-  ATTESTATION_ID_BRAND = -1879047482,
-  ATTESTATION_ID_DEVICE = -1879047481,
-  ATTESTATION_ID_PRODUCT = -1879047480,
-  ATTESTATION_ID_SERIAL = -1879047479,
-  ATTESTATION_ID_IMEI = -1879047478,
-  ATTESTATION_ID_MEID = -1879047477,
-  ATTESTATION_ID_MANUFACTURER = -1879047476,
-  ATTESTATION_ID_MODEL = -1879047475,
-  VENDOR_PATCHLEVEL = 805307086,
-  BOOT_PATCHLEVEL = 805307087,
-  DEVICE_UNIQUE_ATTESTATION = 1879048912,
-  IDENTITY_CREDENTIAL_KEY = 1879048913,
-  STORAGE_KEY = 1879048914,
-  ATTESTATION_ID_SECOND_IMEI = -1879047469,
-  ASSOCIATED_DATA = -1879047192,
-  NONCE = -1879047191,
-  MAC_LENGTH = 805307371,
-  RESET_SINCE_ID_ROTATION = 1879049196,
-  CONFIRMATION_TOKEN = -1879047187,
-  CERTIFICATE_SERIAL = -2147482642,
-  CERTIFICATE_SUBJECT = -1879047185,
-  CERTIFICATE_NOT_BEFORE = 1610613744,
-  CERTIFICATE_NOT_AFTER = 1610613745,
-  MAX_BOOT_LEVEL = 805307378,
+  PURPOSE = (android.hardware.security.keymint.TagType.ENUM_REP | 1) /* 536870913 */,
+  ALGORITHM = (android.hardware.security.keymint.TagType.ENUM | 2) /* 268435458 */,
+  KEY_SIZE = (android.hardware.security.keymint.TagType.UINT | 3) /* 805306371 */,
+  BLOCK_MODE = (android.hardware.security.keymint.TagType.ENUM_REP | 4) /* 536870916 */,
+  DIGEST = (android.hardware.security.keymint.TagType.ENUM_REP | 5) /* 536870917 */,
+  PADDING = (android.hardware.security.keymint.TagType.ENUM_REP | 6) /* 536870918 */,
+  CALLER_NONCE = (android.hardware.security.keymint.TagType.BOOL | 7) /* 1879048199 */,
+  MIN_MAC_LENGTH = (android.hardware.security.keymint.TagType.UINT | 8) /* 805306376 */,
+  EC_CURVE = (android.hardware.security.keymint.TagType.ENUM | 10) /* 268435466 */,
+  RSA_PUBLIC_EXPONENT = (android.hardware.security.keymint.TagType.ULONG | 200) /* 1342177480 */,
+  INCLUDE_UNIQUE_ID = (android.hardware.security.keymint.TagType.BOOL | 202) /* 1879048394 */,
+  RSA_OAEP_MGF_DIGEST = (android.hardware.security.keymint.TagType.ENUM_REP | 203) /* 536871115 */,
+  BOOTLOADER_ONLY = (android.hardware.security.keymint.TagType.BOOL | 302) /* 1879048494 */,
+  ROLLBACK_RESISTANCE = (android.hardware.security.keymint.TagType.BOOL | 303) /* 1879048495 */,
+  HARDWARE_TYPE = (android.hardware.security.keymint.TagType.ENUM | 304) /* 268435760 */,
+  EARLY_BOOT_ONLY = (android.hardware.security.keymint.TagType.BOOL | 305) /* 1879048497 */,
+  ACTIVE_DATETIME = (android.hardware.security.keymint.TagType.DATE | 400) /* 1610613136 */,
+  ORIGINATION_EXPIRE_DATETIME = (android.hardware.security.keymint.TagType.DATE | 401) /* 1610613137 */,
+  USAGE_EXPIRE_DATETIME = (android.hardware.security.keymint.TagType.DATE | 402) /* 1610613138 */,
+  MIN_SECONDS_BETWEEN_OPS = (android.hardware.security.keymint.TagType.UINT | 403) /* 805306771 */,
+  MAX_USES_PER_BOOT = (android.hardware.security.keymint.TagType.UINT | 404) /* 805306772 */,
+  USAGE_COUNT_LIMIT = (android.hardware.security.keymint.TagType.UINT | 405) /* 805306773 */,
+  USER_ID = (android.hardware.security.keymint.TagType.UINT | 501) /* 805306869 */,
+  USER_SECURE_ID = (android.hardware.security.keymint.TagType.ULONG_REP | 502) /* -1610612234 */,
+  NO_AUTH_REQUIRED = (android.hardware.security.keymint.TagType.BOOL | 503) /* 1879048695 */,
+  USER_AUTH_TYPE = (android.hardware.security.keymint.TagType.ENUM | 504) /* 268435960 */,
+  AUTH_TIMEOUT = (android.hardware.security.keymint.TagType.UINT | 505) /* 805306873 */,
+  ALLOW_WHILE_ON_BODY = (android.hardware.security.keymint.TagType.BOOL | 506) /* 1879048698 */,
+  TRUSTED_USER_PRESENCE_REQUIRED = (android.hardware.security.keymint.TagType.BOOL | 507) /* 1879048699 */,
+  TRUSTED_CONFIRMATION_REQUIRED = (android.hardware.security.keymint.TagType.BOOL | 508) /* 1879048700 */,
+  UNLOCKED_DEVICE_REQUIRED = (android.hardware.security.keymint.TagType.BOOL | 509) /* 1879048701 */,
+  APPLICATION_ID = (android.hardware.security.keymint.TagType.BYTES | 601) /* -1879047591 */,
+  APPLICATION_DATA = (android.hardware.security.keymint.TagType.BYTES | 700) /* -1879047492 */,
+  CREATION_DATETIME = (android.hardware.security.keymint.TagType.DATE | 701) /* 1610613437 */,
+  ORIGIN = (android.hardware.security.keymint.TagType.ENUM | 702) /* 268436158 */,
+  ROOT_OF_TRUST = (android.hardware.security.keymint.TagType.BYTES | 704) /* -1879047488 */,
+  OS_VERSION = (android.hardware.security.keymint.TagType.UINT | 705) /* 805307073 */,
+  OS_PATCHLEVEL = (android.hardware.security.keymint.TagType.UINT | 706) /* 805307074 */,
+  UNIQUE_ID = (android.hardware.security.keymint.TagType.BYTES | 707) /* -1879047485 */,
+  ATTESTATION_CHALLENGE = (android.hardware.security.keymint.TagType.BYTES | 708) /* -1879047484 */,
+  ATTESTATION_APPLICATION_ID = (android.hardware.security.keymint.TagType.BYTES | 709) /* -1879047483 */,
+  ATTESTATION_ID_BRAND = (android.hardware.security.keymint.TagType.BYTES | 710) /* -1879047482 */,
+  ATTESTATION_ID_DEVICE = (android.hardware.security.keymint.TagType.BYTES | 711) /* -1879047481 */,
+  ATTESTATION_ID_PRODUCT = (android.hardware.security.keymint.TagType.BYTES | 712) /* -1879047480 */,
+  ATTESTATION_ID_SERIAL = (android.hardware.security.keymint.TagType.BYTES | 713) /* -1879047479 */,
+  ATTESTATION_ID_IMEI = (android.hardware.security.keymint.TagType.BYTES | 714) /* -1879047478 */,
+  ATTESTATION_ID_MEID = (android.hardware.security.keymint.TagType.BYTES | 715) /* -1879047477 */,
+  ATTESTATION_ID_MANUFACTURER = (android.hardware.security.keymint.TagType.BYTES | 716) /* -1879047476 */,
+  ATTESTATION_ID_MODEL = (android.hardware.security.keymint.TagType.BYTES | 717) /* -1879047475 */,
+  VENDOR_PATCHLEVEL = (android.hardware.security.keymint.TagType.UINT | 718) /* 805307086 */,
+  BOOT_PATCHLEVEL = (android.hardware.security.keymint.TagType.UINT | 719) /* 805307087 */,
+  DEVICE_UNIQUE_ATTESTATION = (android.hardware.security.keymint.TagType.BOOL | 720) /* 1879048912 */,
+  IDENTITY_CREDENTIAL_KEY = (android.hardware.security.keymint.TagType.BOOL | 721) /* 1879048913 */,
+  STORAGE_KEY = (android.hardware.security.keymint.TagType.BOOL | 722) /* 1879048914 */,
+  ATTESTATION_ID_SECOND_IMEI = (android.hardware.security.keymint.TagType.BYTES | 723) /* -1879047469 */,
+  MODULE_HASH = (android.hardware.security.keymint.TagType.BYTES | 724) /* -1879047468 */,
+  ASSOCIATED_DATA = (android.hardware.security.keymint.TagType.BYTES | 1000) /* -1879047192 */,
+  NONCE = (android.hardware.security.keymint.TagType.BYTES | 1001) /* -1879047191 */,
+  MAC_LENGTH = (android.hardware.security.keymint.TagType.UINT | 1003) /* 805307371 */,
+  RESET_SINCE_ID_ROTATION = (android.hardware.security.keymint.TagType.BOOL | 1004) /* 1879049196 */,
+  CONFIRMATION_TOKEN = (android.hardware.security.keymint.TagType.BYTES | 1005) /* -1879047187 */,
+  CERTIFICATE_SERIAL = (android.hardware.security.keymint.TagType.BIGNUM | 1006) /* -2147482642 */,
+  CERTIFICATE_SUBJECT = (android.hardware.security.keymint.TagType.BYTES | 1007) /* -1879047185 */,
+  CERTIFICATE_NOT_BEFORE = (android.hardware.security.keymint.TagType.DATE | 1008) /* 1610613744 */,
+  CERTIFICATE_NOT_AFTER = (android.hardware.security.keymint.TagType.DATE | 1009) /* 1610613745 */,
+  MAX_BOOT_LEVEL = (android.hardware.security.keymint.TagType.UINT | 1010) /* 805307378 */,
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl
index a7d1de5..ca19e7e 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl
@@ -35,15 +35,15 @@
 /* @hide */
 @Backing(type="int") @VintfStability
 enum TagType {
-  INVALID = 0,
-  ENUM = 268435456,
-  ENUM_REP = 536870912,
-  UINT = 805306368,
-  UINT_REP = 1073741824,
-  ULONG = 1342177280,
-  DATE = 1610612736,
-  BOOL = 1879048192,
-  BIGNUM = -2147483648,
-  BYTES = -1879048192,
-  ULONG_REP = -1610612736,
+  INVALID = (0 << 28) /* 0 */,
+  ENUM = (1 << 28) /* 268435456 */,
+  ENUM_REP = (2 << 28) /* 536870912 */,
+  UINT = (3 << 28) /* 805306368 */,
+  UINT_REP = (4 << 28) /* 1073741824 */,
+  ULONG = (5 << 28) /* 1342177280 */,
+  DATE = (6 << 28) /* 1610612736 */,
+  BOOL = (7 << 28) /* 1879048192 */,
+  BIGNUM = (8 << 28) /* -2147483648 */,
+  BYTES = (9 << 28) /* -1879048192 */,
+  ULONG_REP = (10 << 28) /* -1610612736 */,
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl b/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
index 137e6b6..72fa773 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
@@ -108,6 +108,7 @@
     INVALID_ISSUER_SUBJECT = -83,
     BOOT_LEVEL_EXCEEDED = -84,
     HARDWARE_NOT_YET_AVAILABLE = -85,
+    MODULE_HASH_ALREADY_SET = -86,
 
     UNIMPLEMENTED = -100,
     VERSION_MISMATCH = -101,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 4ebafee..fc703e9 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -87,12 +87,14 @@
  *        SHA-2 256.
  *      - Unpadded, RSAES-OAEP and RSAES-PKCS1-v1_5 padding modes for RSA encryption.
  *
- * o   ECDSA
+ * o   ECDSA and ECDH
  *
+ *      - IKeyMintDevices must support elliptic curve signing (Purpose::SIGN, Purpose::ATTEST_KEY)
+ *        and key agreement operations (Purpose::AGREE_KEY).
  *      - TRUSTED_ENVIRONMENT IKeyMintDevices must support NIST curves P-224, P-256, P-384 and
  *        P-521.  STRONGBOX IKeyMintDevices must support NIST curve P-256.
- *      - TRUSTED_ENVIRONMENT IKeyMintDevices must support SHA1, SHA-2 224, SHA-2 256, SHA-2
- *        384 and SHA-2 512 digest modes.  STRONGBOX IKeyMintDevices must support SHA-2 256.
+ *      - For signing, TRUSTED_ENVIRONMENT IKeyMintDevices must support SHA1, SHA-2 224, SHA-2 256,
+ *        SHA-2 384 and SHA-2 512 digest modes.  STRONGBOX IKeyMintDevices must support SHA-2 256.
  *      - TRUSTED_ENVRIONMENT IKeyMintDevices must support curve 25519 for Purpose::SIGN (Ed25519,
  *        as specified in RFC 8032), Purpose::ATTEST_KEY (Ed25519) or for KeyPurpose::AGREE_KEY
  *        (X25519, as specified in RFC 7748).  However, a key must have exactly one of these
@@ -302,12 +304,12 @@
      *   PaddingMode::RSA_OAEP, PaddingMode::RSA_PSS, PaddingMode::RSA_PKCS1_1_5_ENCRYPT and
      *   PaddingMode::RSA_PKCS1_1_5_SIGN for RSA keys.
      *
-     * == ECDSA Keys ==
+     * == ECDSA/ECDH Keys ==
      *
-     * Tag::EC_CURVE must be provided to generate an ECDSA key.  If it is not provided, generateKey
-     * must return ErrorCode::UNSUPPORTED_KEY_SIZE or ErrorCode::UNSUPPORTED_EC_CURVE. TEE
-     * IKeyMintDevice implementations must support all required curves.  StrongBox implementations
-     * must support P_256 and no other curves.
+     * Tag::EC_CURVE must be provided to generate an elliptic curve key.  If it is not provided,
+     * generateKey must return ErrorCode::UNSUPPORTED_KEY_SIZE or ErrorCode::UNSUPPORTED_EC_CURVE.
+     * TEE IKeyMintDevice implementations must support all required curves.  StrongBox
+     * implementations must support P_256 and no other curves.
      *
      * Tag::CERTIFICATE_NOT_BEFORE and Tag::CERTIFICATE_NOT_AFTER must be provided to specify the
      * valid date range for the returned X.509 certificate holding the public key. If omitted,
@@ -318,10 +320,10 @@
      * than one purpose should be rejected with ErrorCode::INCOMPATIBLE_PURPOSE.
      * StrongBox implementation do not support CURVE_25519.
      *
-     * Tag::DIGEST specifies digest algorithms that may be used with the new key.  TEE
-     * IKeyMintDevice implementations must support all Digest values (see Digest.aidl) for ECDSA
-     * keys; Ed25519 keys only support Digest::NONE. StrongBox IKeyMintDevice implementations must
-     * support SHA_2_256.
+     * Tag::DIGEST specifies digest algorithms that may be used with the new key when used for
+     * signing.  TEE IKeyMintDevice implementations must support all Digest values (see Digest.aidl)
+     * for ECDSA keys; Ed25519 keys only support Digest::NONE. StrongBox IKeyMintDevice
+     * implementations must support SHA_2_256.
      *
      * == AES Keys ==
      *
@@ -548,10 +550,8 @@
     void deleteKey(in byte[] keyBlob);
 
     /**
-     * Deletes all keys in the hardware keystore.  Used when keystore is reset completely.  After
-     * this function is called all keys with Tag::ROLLBACK_RESISTANCE in their hardware-enforced
-     * authorization lists must be rendered permanently unusable.  Keys without
-     * Tag::ROLLBACK_RESISTANCE may or may not be rendered unusable.
+     * Deletes all keys in the hardware keystore. Used when keystore is reset completely. After
+     * this function is called all keys created previously must be rendered permanently unusable.
      */
     void deleteAllKeys();
 
@@ -828,6 +828,7 @@
      *
      * @param passwordOnly N/A due to the deprecation
      * @param timestampToken N/A due to the deprecation
+     * @deprecated Method has never been used due to design limitations
      */
     void deviceLocked(in boolean passwordOnly, in @nullable TimeStampToken timestampToken);
 
@@ -959,4 +960,18 @@
      * not implemented.  TEE KeyMint implementations must return ErrorCode::UNIMPLEMENTED.
      */
     void sendRootOfTrust(in byte[] rootOfTrust);
+
+    /**
+     * Called by Android to deliver additional attestation information to the IKeyMintDevice.
+     *
+     * IKeyMintDevice must ignore KeyParameters with tags not included in the following list:
+     *
+     * o Tag::MODULE_HASH: holds a hash that must be included in attestations in the moduleHash
+     *   field of the software enforced authorization list.
+     *
+     * @return error ErrorCode::MODULE_HASH_ALREADY_SET if this is not the first time
+     *         setAdditionalAttestationInfo is called with Tag::MODULE_HASH, and the associated
+     *         KeyParamValue of the current call doesn't match the KeyParamValue of the first call.
+     */
+    void setAdditionalAttestationInfo(in KeyParameter[] info);
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index 294c205..2d2f307 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -125,14 +125,25 @@
      * straightforward translation of the KeyMint tag/value parameter lists to ASN.1.
      *
      * KeyDescription ::= SEQUENCE {
-     *     attestationVersion         INTEGER, # Value 300
-     *     attestationSecurityLevel   SecurityLevel, # See below
-     *     keyMintVersion             INTEGER, # Value 300
-     *     keymintSecurityLevel       SecurityLevel, # See below
-     *     attestationChallenge       OCTET_STRING, # Tag::ATTESTATION_CHALLENGE from attestParams
-     *     uniqueId                   OCTET_STRING, # Empty unless key has Tag::INCLUDE_UNIQUE_ID
-     *     softwareEnforced           AuthorizationList, # See below
-     *     hardwareEnforced           AuthorizationList, # See below
+     *     -- attestationVersion must be 400.
+     *     attestationVersion         INTEGER,
+     *     -- attestationSecurityLevel is the SecurityLevel of the location where the attested
+     *     -- key is stored. Must match keymintSecurityLevel.
+     *     attestationSecurityLevel   SecurityLevel,
+     *     -- keyMintVersion must be 400.
+     *     keyMintVersion             INTEGER,
+     *     -- keyMintSecurityLevel is the SecurityLevel of the IKeyMintDevice. Must match
+     *     -- attestationSecurityLevel.
+     *     keyMintSecurityLevel       SecurityLevel,
+     *     -- attestationChallenge contains Tag::ATTESTATION_CHALLENGE from attestParams.
+     *     attestationChallenge       OCTET_STRING,
+     *     -- uniqueId is empty unless the key has Tag::INCLUDE_UNIQUE_ID.
+     *     uniqueId                   OCTET_STRING,
+     *     -- softwareEnforced contains the authorization tags enforced by the Android system.
+     *     softwareEnforced           AuthorizationList,
+     *     -- hardwareEnforced contains the authorization tags enforced by a secure environment
+     *     -- (TEE or StrongBox).
+     *     hardwareEnforced           AuthorizationList,
      * }
      *
      * SecurityLevel ::= ENUMERATED {
@@ -142,12 +153,15 @@
      * }
      *
      * RootOfTrust ::= SEQUENCE {
+     *     -- verifiedBootKey must contain a SHA-256 digest of the public key embedded in the
+     *     -- "vbmeta" partition if the device's bootloader is locked, or 32 bytes of zeroes if the
+     *     -- device's bootloader is unlocked.
      *     verifiedBootKey            OCTET_STRING,
      *     deviceLocked               BOOLEAN,
      *     verifiedBootState          VerifiedBootState,
-     *     # verifiedBootHash must contain 32-byte value that represents the state of all binaries
-     *     # or other components validated by verified boot.  Updating any verified binary or
-     *     # component must cause this value to change.
+     *     -- verifiedBootHash must contain a SHA-256 digest of all binaries and components
+     *     -- validated by Verified Boot. Updating any verified binary or component must cause this
+     *     -- value to change.
      *     verifiedBootHash           OCTET_STRING,
      * }
      *
@@ -158,6 +172,17 @@
      *     Failed                     (3),
      * }
      *
+     * -- Modules contains version information for APEX modules.
+     * -- Note that the Modules information is DER-encoded before being hashed, which requires a
+     * -- specific ordering (lexicographic by encoded value) for the constituent Module entries.
+     * -- This ensures that the ordering of Module entries is predictable and that the resulting
+     * -- SHA-256 hash value is identical for the same set of modules.
+     * Modules ::= SET OF Module
+     * Module ::= SEQUENCE {
+     *     packageName                OCTET_STRING,
+     *     version                    INTEGER, -- As determined at boot time
+     * }
+     *
      * -- Note that the AuthorizationList SEQUENCE is also used in IKeyMintDevice::importWrappedKey
      * -- as a way of describing the authorizations associated with a key that is being securely
      * -- imported.  As such, it includes the ability to describe tags that are only relevant for
@@ -170,11 +195,11 @@
      *     purpose                    [1] EXPLICIT SET OF INTEGER OPTIONAL,
      *     algorithm                  [2] EXPLICIT INTEGER OPTIONAL,
      *     keySize                    [3] EXPLICIT INTEGER OPTIONAL,
-     *     blockMode                  [4] EXPLICIT SET OF INTEGER OPTIONAL, -- symmetric only
+     *     blockMode                  [4] EXPLICIT SET OF INTEGER OPTIONAL, -- Symmetric keys only
      *     digest                     [5] EXPLICIT SET OF INTEGER OPTIONAL,
      *     padding                    [6] EXPLICIT SET OF INTEGER OPTIONAL,
-     *     callerNonce                [7] EXPLICIT NULL OPTIONAL, -- symmetric only
-     *     minMacLength               [8] EXPLICIT INTEGER OPTIONAL, -- symmetric only
+     *     callerNonce                [7] EXPLICIT NULL OPTIONAL, -- Symmetric keys only
+     *     minMacLength               [8] EXPLICIT INTEGER OPTIONAL, -- Symmetric keys only
      *     ecCurve                    [10] EXPLICIT INTEGER OPTIONAL,
      *     rsaPublicExponent          [200] EXPLICIT INTEGER OPTIONAL,
      *     mgfDigest                  [203] EXPLICIT SET OF INTEGER OPTIONAL,
@@ -184,7 +209,7 @@
      *     originationExpireDateTime  [401] EXPLICIT INTEGER OPTIONAL,
      *     usageExpireDateTime        [402] EXPLICIT INTEGER OPTIONAL,
      *     usageCountLimit            [405] EXPLICIT INTEGER OPTIONAL,
-     *     userSecureId               [502] EXPLICIT INTEGER OPTIONAL, -- only used on import
+     *     userSecureId               [502] EXPLICIT INTEGER OPTIONAL, -- Only used on key import
      *     noAuthRequired             [503] EXPLICIT NULL OPTIONAL,
      *     userAuthType               [504] EXPLICIT INTEGER OPTIONAL,
      *     authTimeout                [505] EXPLICIT INTEGER OPTIONAL,
@@ -210,6 +235,8 @@
      *     bootPatchLevel             [719] EXPLICIT INTEGER OPTIONAL,
      *     deviceUniqueAttestation    [720] EXPLICIT NULL OPTIONAL,
      *     attestationIdSecondImei    [723] EXPLICIT OCTET_STRING OPTIONAL,
+     *     -- moduleHash contains a SHA-256 hash of DER-encoded `Modules`
+     *     moduleHash                 [724] EXPLICIT OCTET_STRING OPTIONAL,
      * }
      */
     Certificate[] certificateChain;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index 996e4e3..7ea5f5d 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -901,6 +901,20 @@
     ATTESTATION_ID_SECOND_IMEI = TagType.BYTES | 723,
 
     /**
+     * Tag::MODULE_HASH specifies the SHA-256 hash of the DER-encoded module information (see
+     * KeyCreationResult.aidl for the ASN.1 schema).
+     *
+     * KeyStore clients can retrieve the unhashed DER-encoded module information from Android
+     * via KeyStoreManager.getSupplementaryAttestationInfo.
+     *
+     * This tag is never provided or returned from KeyMint in the key characteristics. It exists
+     * only to define the tag for use in the attestation record.
+     *
+     * Must never appear in KeyCharacteristics.
+     */
+    MODULE_HASH = TagType.BYTES | 724,
+
+    /**
      * OBSOLETE: Do not use.
      *
      * This tag value is included for historical reasons -- in Keymaster it was used to hold
diff --git a/security/keymint/aidl/default/Android.bp b/security/keymint/aidl/default/Android.bp
index fbb6140..0197141 100644
--- a/security/keymint/aidl/default/Android.bp
+++ b/security/keymint/aidl/default/Android.bp
@@ -7,6 +7,24 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+vintf_fragment {
+    name: "android.hardware.security.keymint-service.xml",
+    src: "android.hardware.security.keymint-service.xml",
+    vendor: true,
+}
+
+vintf_fragment {
+    name: "android.hardware.security.sharedsecret-service.xml",
+    src: "android.hardware.security.sharedsecret-service.xml",
+    vendor: true,
+}
+
+vintf_fragment {
+    name: "android.hardware.security.secureclock-service.xml",
+    src: "android.hardware.security.secureclock-service.xml",
+    vendor: true,
+}
+
 // The following target has an insecure implementation of KeyMint where the
 // trusted application (TA) code runs in-process alongside the HAL service
 // code.
@@ -18,11 +36,6 @@
     name: "android.hardware.security.keymint-service",
     relative_install_path: "hw",
     init_rc: ["android.hardware.security.keymint-service.rc"],
-    vintf_fragments: [
-        "android.hardware.security.keymint-service.xml",
-        "android.hardware.security.sharedsecret-service.xml",
-        "android.hardware.security.secureclock-service.xml",
-    ],
     vendor: true,
     cflags: [
         "-Wall",
@@ -51,6 +64,11 @@
     required: [
         "android.hardware.hardware_keystore.xml",
     ],
+    vintf_fragment_modules: [
+        "android.hardware.security.keymint-service.xml",
+        "android.hardware.security.sharedsecret-service.xml",
+        "android.hardware.security.secureclock-service.xml",
+    ],
 }
 
 // The following target has an insecure implementation of KeyMint where the
@@ -65,11 +83,6 @@
     relative_install_path: "hw",
     vendor: true,
     init_rc: ["android.hardware.security.keymint-service.nonsecure.rc"],
-    vintf_fragments: [
-        "android.hardware.security.keymint-service.xml",
-        "android.hardware.security.sharedsecret-service.xml",
-        "android.hardware.security.secureclock-service.xml",
-    ],
     defaults: [
         "keymint_use_latest_hal_aidl_rust",
     ],
@@ -84,11 +97,14 @@
         "libkmr_hal_nonsecure",
         "libkmr_ta_nonsecure",
     ],
-    required: [
-        "android.hardware.hardware_keystore.xml",
+    vintf_fragment_modules: [
+        "android.hardware.security.keymint-service.xml",
+        "android.hardware.security.sharedsecret-service.xml",
+        "android.hardware.security.secureclock-service.xml",
     ],
 }
 
+// The following target declares the latest version of KeyMint.
 prebuilt_etc {
     name: "android.hardware.hardware_keystore.xml",
     sub_dir: "permissions",
@@ -96,6 +112,38 @@
     src: "android.hardware.hardware_keystore.xml",
 }
 
+// The following targets (and underlying XML files) declare specific
+// versions of KeyMint.  Vendors should use the version that matches the
+// version of the KeyMint HAL that the device implements.
+
+prebuilt_etc {
+    name: "android.hardware.hardware_keystore_V1.xml",
+    sub_dir: "permissions",
+    vendor: true,
+    src: "android.hardware.hardware_keystore_V1.xml",
+}
+
+prebuilt_etc {
+    name: "android.hardware.hardware_keystore_V2.xml",
+    sub_dir: "permissions",
+    vendor: true,
+    src: "android.hardware.hardware_keystore_V2.xml",
+}
+
+prebuilt_etc {
+    name: "android.hardware.hardware_keystore_V3.xml",
+    sub_dir: "permissions",
+    vendor: true,
+    src: "android.hardware.hardware_keystore_V3.xml",
+}
+
+prebuilt_etc {
+    name: "android.hardware.hardware_keystore_V4.xml",
+    sub_dir: "permissions",
+    vendor: true,
+    src: "android.hardware.hardware_keystore_V4.xml",
+}
+
 rust_library {
     name: "libkmr_hal_nonsecure",
     crate_name: "kmr_hal_nonsecure",
diff --git a/security/keymint/aidl/default/android.hardware.hardware_keystore.xml b/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
index 4c75596..1ab2133 100644
--- a/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
+++ b/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <permissions>
-  <feature name="android.hardware.hardware_keystore" version="300" />
+  <feature name="android.hardware.hardware_keystore" version="400" />
 </permissions>
diff --git a/security/keymint/aidl/default/android.hardware.hardware_keystore_V1.xml b/security/keymint/aidl/default/android.hardware.hardware_keystore_V1.xml
new file mode 100644
index 0000000..e5a9345
--- /dev/null
+++ b/security/keymint/aidl/default/android.hardware.hardware_keystore_V1.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2021 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.
+-->
+<permissions>
+  <feature name="android.hardware.hardware_keystore" version="100" />
+</permissions>
diff --git a/security/keymint/aidl/default/android.hardware.hardware_keystore_V2.xml b/security/keymint/aidl/default/android.hardware.hardware_keystore_V2.xml
new file mode 100644
index 0000000..2ebf1fe
--- /dev/null
+++ b/security/keymint/aidl/default/android.hardware.hardware_keystore_V2.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2021 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.
+-->
+<permissions>
+  <feature name="android.hardware.hardware_keystore" version="200" />
+</permissions>
diff --git a/security/keymint/aidl/default/android.hardware.hardware_keystore_V3.xml b/security/keymint/aidl/default/android.hardware.hardware_keystore_V3.xml
new file mode 100644
index 0000000..4c75596
--- /dev/null
+++ b/security/keymint/aidl/default/android.hardware.hardware_keystore_V3.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2021 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.
+-->
+<permissions>
+  <feature name="android.hardware.hardware_keystore" version="300" />
+</permissions>
diff --git a/security/keymint/aidl/default/android.hardware.hardware_keystore_V4.xml b/security/keymint/aidl/default/android.hardware.hardware_keystore_V4.xml
new file mode 100644
index 0000000..1ab2133
--- /dev/null
+++ b/security/keymint/aidl/default/android.hardware.hardware_keystore_V4.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2021 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.
+-->
+<permissions>
+  <feature name="android.hardware.hardware_keystore" version="400" />
+</permissions>
diff --git a/security/keymint/aidl/default/android.hardware.security.keymint-service.xml b/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
index 0568ae6..6bdd33e 100644
--- a/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
+++ b/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.security.keymint</name>
-        <version>3</version>
+        <version>4</version>
         <fqname>IKeyMintDevice/default</fqname>
     </hal>
     <hal format="aidl">
diff --git a/security/keymint/aidl/default/file_contexts b/security/keymint/aidl/default/file_contexts
index dce7e3c..41b02d5 100644
--- a/security/keymint/aidl/default/file_contexts
+++ b/security/keymint/aidl/default/file_contexts
@@ -1,3 +1,3 @@
 (/.*)?                                                           u:object_r:vendor_file:s0
 /etc(/.*)?                                                       u:object_r:vendor_configs_file:s0
-/bin/hw/android\.hardware\.security\.keymint-service\.nonsecure  u:object_r:hal_keymint_rust_exec:s0
+/bin/hw/android\.hardware\.security\.keymint-service\.nonsecure  u:object_r:hal_keymint_default_exec:s0
diff --git a/security/keymint/aidl/default/hal/lib.rs b/security/keymint/aidl/default/hal/lib.rs
index 621f077..196cf17 100644
--- a/security/keymint/aidl/default/hal/lib.rs
+++ b/security/keymint/aidl/default/hal/lib.rs
@@ -20,6 +20,19 @@
 use kmr_hal::env::get_property;
 use log::error;
 
+/// Retrieve the most significant attestation property for `name`.
+fn attestation_property(name: &str) -> Vec<u8> {
+    let prop_val = get_property(&format!("ro.product.vendor.{}", name)).unwrap_or_default();
+    if !prop_val.is_empty() {
+        prop_val
+    } else {
+        get_property(&format!("ro.product.{}", name))
+            .unwrap_or_else(|prop_name| format!("{} unavailable", prop_name))
+    }
+    .as_bytes()
+    .to_vec()
+}
+
 /// Populate attestation ID information based on properties (where available).
 /// Retrieving the serial number requires SELinux permission.
 pub fn attestation_id_info() -> kmr_wire::AttestationIdInfo {
@@ -30,12 +43,12 @@
             .to_vec()
     };
     kmr_wire::AttestationIdInfo {
-        brand: prop("ro.product.brand"),
-        device: prop("ro.product.device"),
-        product: prop("ro.product.name"),
+        brand: attestation_property("brand"),
+        device: attestation_property("device"),
+        product: attestation_property("name"),
         serial: prop("ro.serialno"),
-        manufacturer: prop("ro.product.manufacturer"),
-        model: prop("ro.product.model"),
+        manufacturer: attestation_property("manufacturer"),
+        model: attestation_property("model"),
         // Currently modem_simulator always returns one fixed value. See `handleGetIMEI` in
         // device/google/cuttlefish/host/commands/modem_simulator/misc_service.cpp for more details.
         // TODO(b/263188546): Use device-specific IMEI values when available.
@@ -47,11 +60,9 @@
 
 /// Get boot information based on system properties.
 pub fn get_boot_info() -> kmr_wire::SetBootInfoRequest {
-    // No access to a verified boot key.
-    let verified_boot_key = vec![0; 32];
     let vbmeta_digest = get_property("ro.boot.vbmeta.digest").unwrap_or_else(|_| "00".repeat(32));
     let verified_boot_hash = hex::decode(&vbmeta_digest).unwrap_or_else(|_e| {
-        error!("failed to parse hex data in '{}'", vbmeta_digest);
+        error!("failed to parse VBMeta digest hex data in '{vbmeta_digest}': {_e:?}");
         vec![0; 32]
     });
     let device_boot_locked = match get_property("ro.boot.vbmeta.device_state")
@@ -65,6 +76,18 @@
             false
         }
     };
+    let verified_boot_key_digest =
+        get_property("ro.boot.vbmeta.public_key_digest").unwrap_or_else(|_| "00".repeat(32));
+    let verified_boot_key = match device_boot_locked {
+        true => hex::decode(&verified_boot_key_digest).unwrap_or_else(|_e| {
+            error!("Failed to parse Verified Boot key hex data in '{verified_boot_key_digest}': {_e:?}");
+            vec![0; 32]
+        }),
+        // VTS-16+ requires the attested Verified Boot key to be 32 bytes of zeroes when the
+        // bootloader is unlocked, so we ignore the property's value in that case. Behaviour
+        // prior to VTS-16 is unspecified, so it's fine to return the same.
+        false => vec![0; 32],
+    };
     let verified_boot_state = match get_property("ro.boot.verifiedbootstate")
         .unwrap_or_else(|_| "no-prop".to_string())
         .as_str()
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index 7a135e1..da3427a 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
@@ -36,6 +37,7 @@
         "libcrypto",
         "libbase",
         "libgatekeeper",
+        "libvendorsupport",
         "packagemanager_aidl-cpp",
     ],
     static_libs: [
diff --git a/security/keymint/aidl/vts/functional/BootloaderStateTest.cpp b/security/keymint/aidl/vts/functional/BootloaderStateTest.cpp
index c1f6aee..a799ab1 100644
--- a/security/keymint/aidl/vts/functional/BootloaderStateTest.cpp
+++ b/security/keymint/aidl/vts/functional/BootloaderStateTest.cpp
@@ -27,6 +27,7 @@
 #include <libavb/libavb.h>
 #include <libavb_user/avb_ops_user.h>
 #include <remote_prov/remote_prov_utils.h>
+#include <vendorsupport/api_level.h>
 
 #include "KeyMintAidlTestBase.h"
 
@@ -95,6 +96,18 @@
             << "Verified boot state must be \"UNVERIFIED\" aka \"orange\".";
 }
 
+// Check that the attested Verified Boot key is 32 bytes of zeroes since the bootloader is unlocked.
+TEST_P(BootloaderStateTest, VerifiedBootKeyAllZeroes) {
+    // Gate this test to avoid waiver issues.
+    if (get_vendor_api_level() <= AVendorSupport_getVendorApiLevelOf(__ANDROID_API_V__)) {
+        return;
+    }
+
+    std::vector<uint8_t> expectedVbKey(32, 0);
+    ASSERT_EQ(attestedVbKey_, expectedVbKey) << "Verified Boot key digest must be 32 bytes of "
+                                                "zeroes since the bootloader is unlocked.";
+}
+
 // Following error codes from avb_slot_data() mean that slot data was loaded
 // (even if verification failed).
 static inline bool avb_slot_data_loaded(AvbSlotVerifyResult result) {
@@ -109,7 +122,7 @@
     }
 }
 
-// Check that attested vbmeta digest is correct.
+// Check that the attested VBMeta digest is correct.
 TEST_P(BootloaderStateTest, VbmetaDigest) {
     AvbSlotVerifyData* avbSlotData;
     auto suffix = fs_mgr_get_slot_suffix();
@@ -125,21 +138,29 @@
                                   AVB_HASHTREE_ERROR_MODE_EIO, &avbSlotData);
     ASSERT_TRUE(avb_slot_data_loaded(result)) << "Failed to load avb slot data";
 
-    // Unfortunately, bootloader is not required to report the algorithm used
-    // to calculate the digest. There are only two supported options though,
-    // SHA256 and SHA512. Attested VBMeta digest must match one of these.
-    vector<uint8_t> digest256(AVB_SHA256_DIGEST_SIZE);
-    vector<uint8_t> digest512(AVB_SHA512_DIGEST_SIZE);
-
+    vector<uint8_t> sha256Digest(AVB_SHA256_DIGEST_SIZE);
     avb_slot_verify_data_calculate_vbmeta_digest(avbSlotData, AVB_DIGEST_TYPE_SHA256,
-                                                 digest256.data());
-    avb_slot_verify_data_calculate_vbmeta_digest(avbSlotData, AVB_DIGEST_TYPE_SHA512,
-                                                 digest512.data());
+                                                 sha256Digest.data());
 
-    ASSERT_TRUE((attestedVbmetaDigest_ == digest256) || (attestedVbmetaDigest_ == digest512))
-            << "Attested vbmeta digest (" << bin2hex(attestedVbmetaDigest_)
-            << ") does not match computed digest (sha256: " << bin2hex(digest256)
-            << ", sha512: " << bin2hex(digest512) << ").";
+    if (get_vendor_api_level() >= AVendorSupport_getVendorApiLevelOf(__ANDROID_API_V__)) {
+        ASSERT_TRUE(attestedVbmetaDigest_ == sha256Digest)
+                << "Attested VBMeta digest (" << bin2hex(attestedVbmetaDigest_)
+                << ") does not match the expected SHA-256 digest (" << bin2hex(sha256Digest)
+                << ").";
+    } else {
+        // Prior to VSR-15, there was no MUST requirement for the algorithm used by the bootloader
+        // to calculate the VBMeta digest. However, the only two supported options are SHA-256 and
+        // SHA-512, so we expect the attested VBMeta digest to match one of these.
+        vector<uint8_t> sha512Digest(AVB_SHA512_DIGEST_SIZE);
+        avb_slot_verify_data_calculate_vbmeta_digest(avbSlotData, AVB_DIGEST_TYPE_SHA512,
+                                                     sha512Digest.data());
+
+        ASSERT_TRUE((attestedVbmetaDigest_ == sha256Digest) ||
+                    (attestedVbmetaDigest_ == sha512Digest))
+                << "Attested VBMeta digest (" << bin2hex(attestedVbmetaDigest_)
+                << ") does not match the expected digest (SHA-256: " << bin2hex(sha256Digest)
+                << " or SHA-512: " << bin2hex(sha512Digest) << ").";
+    }
 }
 
 INSTANTIATE_KEYMINT_AIDL_TEST(BootloaderStateTest);
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index f669110..9e3e159 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -253,39 +253,14 @@
 
     // Collection of valid attestation ID tags.
     auto attestation_id_tags = AuthorizationSetBuilder();
-    // Use ro.product.brand_for_attestation property for attestation if it is present else fallback
-    // to ro.product.brand
-    std::string prop_value =
-            ::android::base::GetProperty("ro.product.brand_for_attestation", /* default= */ "");
-    if (!prop_value.empty()) {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND,
-                          "ro.product.brand_for_attestation");
-    } else {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
-    }
-    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
-    // Use ro.product.name_for_attestation property for attestation if it is present else fallback
-    // to ro.product.name
-    prop_value = ::android::base::GetProperty("ro.product.name_for_attestation", /* default= */ "");
-    if (!prop_value.empty()) {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT,
-                          "ro.product.name_for_attestation");
-    } else {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
-    }
+
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "brand");
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "device");
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "name");
     add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serialno");
-    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
-                      "ro.product.manufacturer");
-    // Use ro.product.model_for_attestation property for attestation if it is present else fallback
-    // to ro.product.model
-    prop_value =
-            ::android::base::GetProperty("ro.product.model_for_attestation", /* default= */ "");
-    if (!prop_value.empty()) {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL,
-                          "ro.product.model_for_attestation");
-    } else {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
-    }
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER, "manufacturer");
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "model");
+
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
 
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 3b6f92c..06e0f58 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -35,6 +35,7 @@
 #include <openssl/evp.h>
 #include <openssl/mem.h>
 #include <remote_prov/remote_prov_utils.h>
+#include <vendorsupport/api_level.h>
 
 #include <keymaster/cppcose/cppcose.h>
 #include <keymint_support/key_param_output.h>
@@ -159,7 +160,7 @@
     // The multiplier should never be higher than the AIDL version, but can be less
     // (for example, if the implementation is from an earlier version but the HAL service
     // uses the default libraries and so reports the current AIDL version).
-    EXPECT_TRUE((attestation_version / 100) <= aidl_version);
+    EXPECT_LE((attestation_version / 100), aidl_version);
 }
 
 bool avb_verification_enabled() {
@@ -170,12 +171,13 @@
 char nibble2hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
                        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
 
-// Attestations don't contain everything in key authorization lists, so we need to filter the key
-// lists to produce the lists that we expect to match the attestations.
+// Attestations don't completely align with key authorization lists, so we need to filter the lists
+// to include only the tags that are in both.
 auto kTagsToFilter = {
         Tag::CREATION_DATETIME,
         Tag::HARDWARE_TYPE,
         Tag::INCLUDE_UNIQUE_ID,
+        Tag::MODULE_HASH,
 };
 
 AuthorizationSet filtered_tags(const AuthorizationSet& set) {
@@ -244,6 +246,83 @@
     return boot_patch_level(key_characteristics_);
 }
 
+std::optional<vector<uint8_t>> KeyMintAidlTestBase::getModuleHash() {
+    if (AidlVersion() < 4) {
+        // The `MODULE_HASH` tag was introduced in v4 of the HAL; earlier versions should never
+        // expect to encounter it.
+        return std::nullopt;
+    }
+
+    // The KeyMint instance should already have been informed of the `MODULE_HASH` value for the
+    // currently running system. Generate a single attestation so we can find out what the value
+    // is.
+    auto challenge = "hello";
+    auto app_id = "foo";
+    auto params = AuthorizationSetBuilder()
+                          .EcdsaSigningKey(EcCurve::P_256)
+                          .Digest(Digest::NONE)
+                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                          .AttestationChallenge(challenge)
+                          .AttestationApplicationId(app_id)
+                          .SetDefaultValidity();
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+    vector<Certificate> chain;
+    auto result = GenerateKey(params, &key_blob, &key_characteristics, &chain);
+    if (result != ErrorCode::OK) {
+        ADD_FAILURE() << "Failed to generate attestation:" << result;
+        return std::nullopt;
+    }
+    KeyBlobDeleter deleter(keymint_, key_blob);
+    if (chain.empty()) {
+        ADD_FAILURE() << "No attestation cert";
+        return std::nullopt;
+    }
+
+    // Parse the attestation record in the leaf cert.
+    X509_Ptr cert(parse_cert_blob(chain[0].encodedCertificate));
+    if (cert.get() == nullptr) {
+        ADD_FAILURE() << "Failed to parse attestation cert";
+        return std::nullopt;
+    }
+    ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
+    if (attest_rec == nullptr) {
+        ADD_FAILURE() << "Failed to find attestation extension";
+        return std::nullopt;
+    }
+    AuthorizationSet att_sw_enforced;
+    AuthorizationSet att_hw_enforced;
+    uint32_t att_attestation_version;
+    uint32_t att_keymint_version;
+    SecurityLevel att_attestation_security_level;
+    SecurityLevel att_keymint_security_level;
+    vector<uint8_t> att_challenge;
+    vector<uint8_t> att_unique_id;
+    vector<uint8_t> att_app_id;
+
+    auto error = parse_attestation_record(attest_rec->data,                 //
+                                          attest_rec->length,               //
+                                          &att_attestation_version,         //
+                                          &att_attestation_security_level,  //
+                                          &att_keymint_version,             //
+                                          &att_keymint_security_level,      //
+                                          &att_challenge,                   //
+                                          &att_sw_enforced,                 //
+                                          &att_hw_enforced,                 //
+                                          &att_unique_id);
+    if (error != ErrorCode::OK) {
+        ADD_FAILURE() << "Failed to parse attestation extension";
+        return std::nullopt;
+    }
+
+    // The module hash should be present in the software-enforced list.
+    if (!att_sw_enforced.Contains(TAG_MODULE_HASH)) {
+        ADD_FAILURE() << "No TAG_MODULE_HASH in attestation extension";
+        return std::nullopt;
+    }
+    return att_sw_enforced.GetTagValue(TAG_MODULE_HASH);
+}
+
 /**
  * An API to determine device IDs attestation is required or not,
  * which is mandatory for KeyMint version 2 and first_api_level 33 or greater.
@@ -280,12 +359,7 @@
     }
 
     // Curve 25519 was included in version 2 of the KeyMint interface.
-    int32_t version = 0;
-    auto status = keymint_->getInterfaceVersion(&version);
-    if (!status.isOk()) {
-        ADD_FAILURE() << "Failed to determine interface version";
-    }
-    return version >= 2;
+    return AidlVersion() >= 2;
 }
 
 void KeyMintAidlTestBase::InitializeKeyMint(std::shared_ptr<IKeyMintDevice> keyMint) {
@@ -303,6 +377,20 @@
     os_version_ = getOsVersion();
     os_patch_level_ = getOsPatchlevel();
     vendor_patch_level_ = getVendorPatchlevel();
+
+    // TODO(b/369375199): temporary code, remove when apexd -> keystore2 -> KeyMint transmission
+    // of module info happens.
+    {
+        GTEST_LOG_(INFO) << "Setting MODULE_HASH to fake value as fallback";
+        // Ensure that a MODULE_HASH value is definitely present in KeyMint (if it's >= v4).
+        vector<uint8_t> fakeModuleHash = {
+                0xf3, 0xf1, 0x1f, 0xe5, 0x13, 0x05, 0xfe, 0xfa, 0xe9, 0xc3, 0x53,
+                0xef, 0x69, 0xdf, 0x9f, 0xd7, 0x0c, 0x1e, 0xcc, 0x2c, 0x2c, 0x62,
+                0x1f, 0x5e, 0x2c, 0x1d, 0x19, 0xa1, 0xfd, 0xac, 0xa1, 0xb4,
+        };
+        vector<KeyParameter> info = {Authorization(TAG_MODULE_HASH, fakeModuleHash)};
+        keymint_->setAdditionalAttestationInfo(info);
+    }
 }
 
 int32_t KeyMintAidlTestBase::AidlVersion() const {
@@ -330,6 +418,13 @@
 ErrorCode KeyMintAidlTestBase::GenerateKey(const AuthorizationSet& key_desc,
                                            vector<uint8_t>* key_blob,
                                            vector<KeyCharacteristics>* key_characteristics) {
+    return GenerateKey(key_desc, key_blob, key_characteristics, &cert_chain_);
+}
+
+ErrorCode KeyMintAidlTestBase::GenerateKey(const AuthorizationSet& key_desc,
+                                           vector<uint8_t>* key_blob,
+                                           vector<KeyCharacteristics>* key_characteristics,
+                                           vector<Certificate>* cert_chain) {
     std::optional<AttestationKey> attest_key = std::nullopt;
     vector<Certificate> attest_cert_chain;
     // If an attestation is requested, but the system is RKP-only, we need to supply an explicit
@@ -353,11 +448,10 @@
         attest_key.value().issuerSubjectName = make_name_from_str("Android Keystore Key");
     }
 
-    ErrorCode error =
-            GenerateKey(key_desc, attest_key, key_blob, key_characteristics, &cert_chain_);
+    ErrorCode error = GenerateKey(key_desc, attest_key, key_blob, key_characteristics, cert_chain);
 
     if (error == ErrorCode::OK && attest_cert_chain.size() > 0) {
-        cert_chain_.push_back(attest_cert_chain[0]);
+        cert_chain->push_back(attest_cert_chain[0]);
     }
 
     return error;
@@ -1053,13 +1147,12 @@
                 int openssl_padding = RSA_NO_PADDING;
                 switch (padding) {
                     case PaddingMode::NONE:
-                        ASSERT_TRUE(data_size <= key_len);
+                        ASSERT_LE(data_size, key_len);
                         ASSERT_EQ(key_len, signature.size());
                         openssl_padding = RSA_NO_PADDING;
                         break;
                     case PaddingMode::RSA_PKCS1_1_5_SIGN:
-                        ASSERT_TRUE(data_size + kPkcs1UndigestedSignaturePaddingOverhead <=
-                                    key_len);
+                        ASSERT_LE(data_size + kPkcs1UndigestedSignaturePaddingOverhead, key_len);
                         openssl_padding = RSA_PKCS1_PADDING;
                         break;
                     default:
@@ -1342,12 +1435,11 @@
 }
 
 bool KeyMintAidlTestBase::IsRkpSupportRequired() const {
-    // This is technically not a match to the requirements for S chipsets,
-    // however when S shipped there was a bug in the test that skipped the
-    // tests if KeyMint 2 was not on the system. So we allowed many chipests
-    // to ship without RKP support. In T we hardened the requirements around
-    // support for RKP, so relax the test to match.
-    return get_vsr_api_level() >= __ANDROID_API_T__;
+    // This is technically weaker than the VSR-12 requirements, but when
+    // Android 12 shipped, there was a bug that skipped the tests if KeyMint
+    // 2 was not present. As a result, many chipsets were allowed to ship
+    // without RKP support. The RKP requirements were hardened in VSR-13.
+    return get_vendor_api_level() >= __ANDROID_API_T__;
 }
 
 vector<uint32_t> KeyMintAidlTestBase::ValidKeySizes(Algorithm algorithm) {
@@ -1598,11 +1690,11 @@
                                                  vector<uint8_t>* key_blob,
                                                  vector<KeyCharacteristics>* key_characteristics,
                                                  vector<Certificate>* cert_chain) {
-    // The original specification for KeyMint v1 required ATTEST_KEY not be combined
-    // with any other key purpose, but the original VTS tests incorrectly did exactly that.
-    // This means that a device that launched prior to Android T (API level 33) may
-    // accept or even require KeyPurpose::SIGN too.
-    if (get_vsr_api_level() < __ANDROID_API_T__) {
+    // The original specification for KeyMint v1 (introduced in Android 12) required ATTEST_KEY not
+    // be combined with any other key purpose, but the original VTS-12 tests incorrectly did exactly
+    // that. The tests were fixed in VTS-13 (vendor API level 33). This means that devices with
+    // vendor API level < 33 may accept or even require KeyPurpose::SIGN too.
+    if (get_vendor_api_level() < __ANDROID_API_T__) {
         AuthorizationSet key_desc_plus_sign = key_desc;
         key_desc_plus_sign.push_back(TAG_PURPOSE, KeyPurpose::SIGN);
 
@@ -1727,13 +1819,19 @@
     OPENSSL_free(cert_issuer);
 }
 
-int get_vsr_api_level() {
+int get_vendor_api_level() {
+    // Android 13+ builds have the `ro.vendor.api_level` system property. See
+    // https://source.android.com/docs/core/architecture/api-flags#determine_vendor_api_level_android_13.
     int vendor_api_level = ::android::base::GetIntProperty("ro.vendor.api_level", -1);
     if (vendor_api_level != -1) {
         return vendor_api_level;
     }
 
-    // Android S and older devices do not define ro.vendor.api_level
+    // Android 12 builds have the `ro.board.api_level` and `ro.board.first_api_level` system
+    // properties, which are only expected to be populated for GRF SoCs on Android 12 builds. Note
+    // that they are populated automatically by the build system starting in Android 15, but we use
+    // `ro.vendor.api_level` on such builds (see above). For details, see
+    // https://docs.partner.android.com/gms/building/integrating/extending-os-upgrade-support-windows#new-system-properties.
     vendor_api_level = ::android::base::GetIntProperty("ro.board.api_level", -1);
     if (vendor_api_level == -1) {
         vendor_api_level = ::android::base::GetIntProperty("ro.board.first_api_level", -1);
@@ -1745,11 +1843,12 @@
         EXPECT_NE(product_api_level, -1) << "Could not find ro.build.version.sdk";
     }
 
-    // VSR API level is the minimum of vendor_api_level and product_api_level.
-    if (vendor_api_level == -1 || vendor_api_level > product_api_level) {
+    // If the `ro.board.api_level` and `ro.board.first_api_level` properties aren't populated, it
+    // means the build doesn't have a GRF SoC, so the product API level should be used.
+    if (vendor_api_level == -1) {
         return product_api_level;
     }
-    return vendor_api_level;
+    return std::min(product_api_level, vendor_api_level);
 }
 
 bool is_gsi_image() {
@@ -1816,16 +1915,29 @@
         }
     }
 
-    // Verified boot key should be all 0's if the boot state is not verified or self signed
+    if (get_vendor_api_level() > AVendorSupport_getVendorApiLevelOf(__ANDROID_API_V__)) {
+        // The Verified Boot key field should be exactly 32 bytes since it
+        // contains the SHA-256 hash of the key on locked devices or 32 bytes
+        // of zeroes on unlocked devices. This wasn't checked for earlier
+        // versions of the KeyMint HAL, so we version-gate the strict check.
+        EXPECT_EQ(verified_boot_key.size(), 32);
+    } else if (get_vendor_api_level() == AVendorSupport_getVendorApiLevelOf(__ANDROID_API_V__)) {
+        // The Verified Boot key field should be:
+        //   - Exactly 32 bytes on locked devices since it should contain
+        //     the SHA-256 hash of the key, or
+        //   - Up to 32 bytes of zeroes on unlocked devices (behaviour on
+        //     unlocked devices isn't specified in the HAL interface
+        //     specification).
+        // Thus, we can't check for strict equality in case unlocked devices
+        // report values with less than 32 bytes. This wasn't checked for
+        // earlier versions of the KeyMint HAL, so we version-gate the check.
+        EXPECT_LE(verified_boot_key.size(), 32);
+    }
+
+    // Verified Boot key should be all zeroes if the boot state is "orange".
     std::string empty_boot_key(32, '\0');
     std::string verified_boot_key_str((const char*)verified_boot_key.data(),
                                       verified_boot_key.size());
-    if (get_vsr_api_level() >= __ANDROID_API_V__) {
-        // The attestation should contain the SHA-256 hash of the verified boot
-        // key.  However, this was not checked for earlier versions of the KeyMint
-        // HAL so only be strict for VSR-V and above.
-        EXPECT_LE(verified_boot_key.size(), 32);
-    }
     EXPECT_NE(property_get("ro.boot.verifiedbootstate", property_value, ""), 0);
     if (!strcmp(property_value, "green")) {
         EXPECT_EQ(verified_boot_state, VerifiedBoot::VERIFIED);
@@ -2140,6 +2252,33 @@
 
 namespace {
 
+std::optional<std::string> validateP256Point(const std::vector<uint8_t>& x_buffer,
+                                             const std::vector<uint8_t>& y_buffer) {
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    if (group.get() == nullptr) {
+        return "Error creating EC group by curve name for prime256v1";
+    }
+
+    auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
+    BIGNUM_Ptr x(BN_bin2bn(x_buffer.data(), x_buffer.size(), nullptr));
+    BIGNUM_Ptr y(BN_bin2bn(y_buffer.data(), y_buffer.size(), nullptr));
+    if (!EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), x.get(), y.get(), nullptr)) {
+        return "Failed to set affine coordinates.";
+    }
+    if (!EC_POINT_is_on_curve(group.get(), point.get(), nullptr)) {
+        return "Point is not on curve.";
+    }
+    if (EC_POINT_is_at_infinity(group.get(), point.get())) {
+        return "Point is at infinity.";
+    }
+    const auto* generator = EC_GROUP_get0_generator(group.get());
+    if (!EC_POINT_cmp(group.get(), generator, point.get(), nullptr)) {
+        return "Point is equal to generator.";
+    }
+
+    return std::nullopt;
+}
+
 void check_cose_key(const vector<uint8_t>& data, bool testMode) {
     auto [parsedPayload, __, payloadParseErr] = cppbor::parse(data);
     ASSERT_TRUE(parsedPayload) << "Key parse failed: " << payloadParseErr;
@@ -2173,6 +2312,24 @@
                              "  -3 : \\{(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}\\},\n"  // pub_y: data
                              "\\}"));
     }
+
+    ASSERT_TRUE(parsedPayload->asMap()) << "CBOR item was not a map";
+
+    ASSERT_TRUE(parsedPayload->asMap()->get(CoseKey::Label::PUBKEY_X))
+            << "CBOR map did not contain x coordinate of public key";
+    ASSERT_TRUE(parsedPayload->asMap()->get(CoseKey::Label::PUBKEY_X)->asBstr())
+            << "x coordinate of public key was not a bstr";
+    const auto& x = parsedPayload->asMap()->get(CoseKey::Label::PUBKEY_X)->asBstr()->value();
+
+    ASSERT_TRUE(parsedPayload->asMap()->get(CoseKey::Label::PUBKEY_Y))
+            << "CBOR map did not contain y coordinate of public key";
+    ASSERT_TRUE(parsedPayload->asMap()->get(CoseKey::Label::PUBKEY_Y)->asBstr())
+            << "y coordinate of public key was not a bstr";
+    const auto& y = parsedPayload->asMap()->get(CoseKey::Label::PUBKEY_Y)->asBstr()->value();
+
+    auto errorMessage = validateP256Point(x, y);
+    EXPECT_EQ(errorMessage, std::nullopt)
+            << *errorMessage << " x: " << bin2hex(x) << " y: " << bin2hex(y);
 }
 
 }  // namespace
@@ -2265,7 +2422,7 @@
     } else if (result == ErrorCode::INVALID_TAG) {
         // Depending on the situation, other error codes may be acceptable.  First, allow older
         // implementations to use INVALID_TAG.
-        ASSERT_FALSE(get_vsr_api_level() > __ANDROID_API_T__)
+        ASSERT_FALSE(get_vendor_api_level() > __ANDROID_API_T__)
                 << "It is a specification violation for INVALID_TAG to be returned due to ID "
                 << "mismatch in a Device ID Attestation call. INVALID_TAG is only intended to "
                 << "be used for a case where updateAad() is called after update(). As of "
@@ -2275,7 +2432,7 @@
         // ATTESTATION_IDS_NOT_PROVISIONED in this case.
         ASSERT_TRUE((tag == TAG_ATTESTATION_ID_IMEI || tag == TAG_ATTESTATION_ID_MEID ||
                      tag == TAG_ATTESTATION_ID_SECOND_IMEI))
-                << "incorrect error code on attestation ID mismatch";
+                << "incorrect error code on attestation ID mismatch for " << tag;
     } else {
         ADD_FAILURE() << "Error code " << result
                       << " returned on attestation ID mismatch, should be CANNOT_ATTEST_IDS";
@@ -2357,7 +2514,7 @@
 
     FILE* pipe = popen(command.c_str(), "r");
     if (!pipe) {
-        LOG(ERROR) << "popen failed.";
+        GTEST_LOG_(ERROR) << "popen failed.";
         return result;
     }
 
@@ -2383,7 +2540,7 @@
     std::string output = exec_command(cmd);
 
     if (output.empty()) {
-        LOG(ERROR) << "Command failed. Cmd: " << cmd;
+        GTEST_LOG_(ERROR) << "Command failed. Cmd: " << cmd;
         return "";
     }
 
@@ -2391,19 +2548,57 @@
             ::android::base::Tokenize(::android::base::Trim(output), "Device IMEI:");
 
     if (out.size() != 1) {
-        LOG(ERROR) << "Error in parsing the command output. Cmd: " << cmd;
+        GTEST_LOG_(ERROR) << "Error in parsing the command output. Cmd: " << cmd;
         return "";
     }
 
     std::string imei = ::android::base::Trim(out[0]);
     if (imei.compare("null") == 0) {
-        LOG(WARNING) << "Failed to get IMEI from Telephony service: value is null. Cmd: " << cmd;
+        GTEST_LOG_(WARNING) << "Failed to get IMEI from Telephony service: value is null. Cmd: "
+                            << cmd;
         return "";
     }
 
     return imei;
 }
 
+std::optional<std::string> get_attestation_id(const char* prop) {
+    // The frameworks code (in AndroidKeyStoreKeyPairGeneratorSpi.java) populates device ID
+    // values from one of 3 places, so the same logic needs to be reproduced here so the tests
+    // check what's expected correctly.
+    //
+    // In order of preference, the properties checked are:
+    //
+    // 1) `ro.product.<device-id>_for_attestation`: This should only be set in special cases; in
+    //     particular, AOSP builds for reference devices use a different value than the normal
+    //     builds for the same device (e.g. model of "aosp_raven" instead of "raven").
+    ::android::String8 prop_name =
+            ::android::String8::format("ro.product.%s_for_attestation", prop);
+    std::string prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
+    if (!prop_value.empty()) {
+        return prop_value;
+    }
+
+    // 2) `ro.product.vendor.<device-id>`: This property refers to the vendor code, and so is
+    //    retained even in a GSI environment.
+    prop_name = ::android::String8::format("ro.product.vendor.%s", prop);
+    prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
+    if (!prop_value.empty()) {
+        return prop_value;
+    }
+
+    // 3) `ro.product.<device-id>`: Note that this property is replaced by a default value when
+    //    running a GSI environment, and so will *not* match the value expected/used by the
+    //    vendor code on the device.
+    prop_name = ::android::String8::format("ro.product.%s", prop);
+    prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
+    if (!prop_value.empty()) {
+        return prop_value;
+    }
+
+    return std::nullopt;
+}
+
 }  // namespace test
 
 }  // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 0368bba..6c327bb 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <functional>
+#include <optional>
 #include <string_view>
 
 #include <aidl/Gtest.h>
@@ -102,6 +103,7 @@
     uint32_t vendor_patch_level() { return vendor_patch_level_; }
     uint32_t boot_patch_level(const vector<KeyCharacteristics>& key_characteristics);
     uint32_t boot_patch_level();
+    std::optional<vector<uint8_t>> getModuleHash();
     bool isDeviceIdAttestationRequired();
     bool isSecondImeiIdAttestationRequired();
     std::optional<bool> isRkpOnly();
@@ -113,6 +115,10 @@
     ErrorCode GenerateKey(const AuthorizationSet& key_desc, vector<uint8_t>* key_blob,
                           vector<KeyCharacteristics>* key_characteristics);
 
+    ErrorCode GenerateKey(const AuthorizationSet& key_desc, vector<uint8_t>* key_blob,
+                          vector<KeyCharacteristics>* key_characteristics,
+                          vector<Certificate>* cert_chain);
+
     ErrorCode GenerateKey(const AuthorizationSet& key_desc,
                           const optional<AttestationKey>& attest_key, vector<uint8_t>* key_blob,
                           vector<KeyCharacteristics>* key_characteristics,
@@ -384,18 +390,24 @@
                                     const string& plaintext, const string& exp_cipher_text);
 };
 
-// If the given property is available, add it to the tag set under the given tag ID.
+// If the given string is non-empty, add it to the tag set under the given tag ID.
 template <Tag tag>
-void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
-                       const char* prop) {
-    std::string prop_value = ::android::base::GetProperty(prop, /* default= */ "");
+void add_tag(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
+             const std::string& prop_value) {
     if (!prop_value.empty()) {
         tags->Authorization(ttag, prop_value.data(), prop_value.size());
     }
 }
 
-// Return the VSR API level for this device.
-int get_vsr_api_level();
+// If the given property is available, add it to the tag set under the given tag ID.
+template <Tag tag>
+void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
+                       const char* prop) {
+    add_tag(tags, ttag, ::android::base::GetProperty(prop, /* default= */ ""));
+}
+
+// Return the vendor API level for this device.
+int get_vendor_api_level();
 
 // Indicate whether the test is running on a GSI image.
 bool is_gsi_image();
@@ -431,6 +443,20 @@
 std::optional<int32_t> keymint_feature_value(bool strongbox);
 std::string get_imei(int slot);
 
+// Retrieve a device ID property value, to match what is expected in attestations.
+std::optional<std::string> get_attestation_id(const char* prop);
+
+// Add the appropriate attestation device ID tag value to the provided `AuthorizationSetBuilder`,
+// if found.
+template <Tag tag>
+void add_attestation_id(AuthorizationSetBuilder* attestation_id_tags,
+                        TypedTag<TagType::BYTES, tag> tag_type, const char* prop) {
+    auto prop_value = get_attestation_id(prop);
+    if (prop_value.has_value()) {
+        add_tag(attestation_id_tags, tag_type, prop_value.value());
+    }
+}
+
 AuthorizationSet HwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
 AuthorizationSet SwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
 ::testing::AssertionResult ChainSignaturesAreValid(const vector<Certificate>& chain,
@@ -444,29 +470,6 @@
                              ::android::PrintInstanceNameToString);                  \
     GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name);
 
-// Use `ro.product.<property>_for_attestation` property for attestation if it is present else
-// fallback to use `ro.product.vendor.<property>` if it is present else fallback to
-// `ro.product.<property>`. Similar logic can be seen in Java method `getVendorDeviceIdProperty`
-// in frameworks/base/core/java/android/os/Build.java.
-template <Tag tag>
-void add_attestation_id(AuthorizationSetBuilder* attestation_id_tags,
-                        TypedTag<TagType::BYTES, tag> tag_type, const char* prop) {
-    ::android::String8 prop_name =
-            ::android::String8::format("ro.product.%s_for_attestation", prop);
-    std::string prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
-    if (!prop_value.empty()) {
-        add_tag_from_prop(attestation_id_tags, tag_type, prop_name.c_str());
-    } else {
-        prop_name = ::android::String8::format("ro.product.vendor.%s", prop);
-        prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
-        if (!prop_value.empty()) {
-            add_tag_from_prop(attestation_id_tags, tag_type, prop_name.c_str());
-        } else {
-            prop_name = ::android::String8::format("ro.product.%s", prop);
-            add_tag_from_prop(attestation_id_tags, tag_type, prop_name.c_str());
-        }
-    }
-}
 }  // namespace test
 
 }  // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 527b5e0..743928e 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -42,6 +42,8 @@
 #include <keymint_support/key_param_output.h>
 #include <keymint_support/openssl_utils.h>
 
+#include <vendorsupport/api_level.h>
+
 #include "KeyMintAidlTestBase.h"
 
 using aidl::android::hardware::security::keymint::AuthorizationSet;
@@ -643,6 +645,7 @@
         // Verify that App data, ROT and auth timeout are NOT included.
         EXPECT_FALSE(auths.Contains(TAG_ROOT_OF_TRUST));
         EXPECT_FALSE(auths.Contains(TAG_APPLICATION_DATA));
+        EXPECT_FALSE(auths.Contains(TAG_MODULE_HASH));
         EXPECT_FALSE(auths.Contains(TAG_AUTH_TIMEOUT, 301U));
 
         // None of the tests specify CREATION_DATETIME so check that the KeyMint implementation
@@ -2583,7 +2586,8 @@
     auto result = GenerateKey(
             AuthorizationSetBuilder().EcdsaKey(256).Digest(Digest::NONE).SetDefaultValidity());
     ASSERT_TRUE(result == ErrorCode::UNSUPPORTED_KEY_SIZE ||
-                result == ErrorCode::UNSUPPORTED_EC_CURVE);
+                result == ErrorCode::UNSUPPORTED_EC_CURVE)
+            << "unexpected result " << result;
 }
 
 /*
@@ -2604,7 +2608,7 @@
                                       .SigningKey()
                                       .Digest(Digest::NONE)
                                       .SetDefaultValidity());
-    ASSERT_TRUE(result == ErrorCode::INVALID_ARGUMENT);
+    ASSERT_EQ(result, ErrorCode::INVALID_ARGUMENT);
 }
 
 /*
@@ -3183,7 +3187,8 @@
     string result;
     ErrorCode finish_error_code = Finish(message, &result);
     EXPECT_TRUE(finish_error_code == ErrorCode::INVALID_INPUT_LENGTH ||
-                finish_error_code == ErrorCode::INVALID_ARGUMENT);
+                finish_error_code == ErrorCode::INVALID_ARGUMENT)
+            << "unexpected error code " << finish_error_code;
 
     // Very large message that should exceed the transfer buffer size of any reasonable TEE.
     message = string(128 * 1024, 'a');
@@ -3193,7 +3198,8 @@
                                               .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
     finish_error_code = Finish(message, &result);
     EXPECT_TRUE(finish_error_code == ErrorCode::INVALID_INPUT_LENGTH ||
-                finish_error_code == ErrorCode::INVALID_ARGUMENT);
+                finish_error_code == ErrorCode::INVALID_ARGUMENT)
+            << "unexpected error code " << finish_error_code;
 }
 
 /*
@@ -3247,7 +3253,8 @@
                                                   .Digest(Digest::NONE)
                                                   .Digest(Digest::SHA1)
                                                   .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN));
-    ASSERT_TRUE(result == ErrorCode::UNSUPPORTED_DIGEST || result == ErrorCode::INVALID_ARGUMENT);
+    ASSERT_TRUE(result == ErrorCode::UNSUPPORTED_DIGEST || result == ErrorCode::INVALID_ARGUMENT)
+            << "unexpected result " << result;
 
     ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST,
               Begin(KeyPurpose::SIGN,
@@ -3420,7 +3427,8 @@
         }
 
         auto rc = DeleteKey();
-        ASSERT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED);
+        ASSERT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED)
+                << "unexpected result " << rc;
     }
 }
 
@@ -4150,13 +4158,15 @@
  * when the EC_CURVE is not explicitly specified.
  */
 TEST_P(ImportKeyTest, EcdsaSuccessCurveNotSpecified) {
-    if (get_vsr_api_level() < __ANDROID_API_V__) {
+    int vendor_api_level = get_vendor_api_level();
+    if (vendor_api_level < AVendorSupport_getVendorApiLevelOf(__ANDROID_API_V__)) {
         /*
          * The KeyMint spec was previously not clear as to whether EC_CURVE was optional on import
-         * of EC keys. However, this was not checked at the time so we can only be strict about
-         * checking this for implementations at VSR-V or later.
+         * of EC keys. However, this was not checked at the time, so we version-gate the strict
+         * check.
          */
-        GTEST_SKIP() << "Skipping EC_CURVE on import only strict >= VSR-V";
+        GTEST_SKIP() << "Applies only to vendor API level >= 202404, but this device is: "
+                     << vendor_api_level;
     }
 
     ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
@@ -5308,15 +5318,15 @@
         "8564");
 
 TEST_P(ImportWrappedKeyTest, RsaKey) {
-    int vsr_api_level = get_vsr_api_level();
-    if (vsr_api_level < __ANDROID_API_V__) {
+    int vendor_api_level = get_vendor_api_level();
+    if (vendor_api_level < AVendorSupport_getVendorApiLevelOf(__ANDROID_API_V__)) {
         /*
          * The Keymaster v4 spec introduced `importWrappedKey()` and did not restrict it to
          * just symmetric keys.  However, the import of asymmetric wrapped keys was not tested
-         * at the time, so we can only be strict about checking this for implementations claiming
-         * support for VSR API level 35 and above.
+         * at the time, so we version-gate the strict check.
          */
-        GTEST_SKIP() << "Applies only to VSR API level 35, this device is: " << vsr_api_level;
+        GTEST_SKIP() << "Applies only to vendor API level >= 202404, but this device is: "
+                     << vendor_api_level;
     }
 
     auto wrapping_key_desc = AuthorizationSetBuilder()
@@ -5339,15 +5349,15 @@
 }
 
 TEST_P(ImportWrappedKeyTest, EcKey) {
-    int vsr_api_level = get_vsr_api_level();
-    if (vsr_api_level < __ANDROID_API_V__) {
+    int vendor_api_level = get_vendor_api_level();
+    if (vendor_api_level < AVendorSupport_getVendorApiLevelOf(__ANDROID_API_V__)) {
         /*
          * The Keymaster v4 spec introduced `importWrappedKey()` and did not restrict it to
          * just symmetric keys.  However, the import of asymmetric wrapped keys was not tested
-         * at the time, so we can only be strict about checking this for implementations claiming
-         * support for VSR API level 35 and above.
+         * at the time, so we version-gate the strict check.
          */
-        GTEST_SKIP() << "Applies only to VSR API level 35, this device is: " << vsr_api_level;
+        GTEST_SKIP() << "Applies only to vendor API level >= 202404, but this device is: "
+                     << vendor_api_level;
     }
 
     auto wrapping_key_desc = AuthorizationSetBuilder()
@@ -5704,7 +5714,8 @@
     // is checked against those values, and found absent.
     auto result = Begin(KeyPurpose::DECRYPT, params);
     EXPECT_TRUE(result == ErrorCode::UNSUPPORTED_MGF_DIGEST ||
-                result == ErrorCode::INCOMPATIBLE_MGF_DIGEST);
+                result == ErrorCode::INCOMPATIBLE_MGF_DIGEST)
+            << "unexpected result " << result;
 }
 
 /*
@@ -5969,14 +5980,16 @@
                                                      .BlockMode(BlockMode::ECB)
                                                      .Padding(PaddingMode::NONE));
     EXPECT_TRUE(result == ErrorCode::INCOMPATIBLE_BLOCK_MODE ||
-                result == ErrorCode::UNSUPPORTED_BLOCK_MODE);
+                result == ErrorCode::UNSUPPORTED_BLOCK_MODE)
+            << "unexpected result " << result;
 
     result = Begin(KeyPurpose::ENCRYPT, AuthorizationSetBuilder()
                                                 .BlockMode(BlockMode::ECB)
                                                 .Padding(PaddingMode::NONE)
                                                 .Padding(PaddingMode::PKCS7));
     EXPECT_TRUE(result == ErrorCode::INCOMPATIBLE_PADDING_MODE ||
-                result == ErrorCode::UNSUPPORTED_PADDING_MODE);
+                result == ErrorCode::UNSUPPORTED_PADDING_MODE)
+            << "unexpected result " << result;
 }
 
 /*
@@ -8296,21 +8309,15 @@
         GTEST_SKIP() << "Option --arm_deleteAllKeys not set";
         return;
     }
+    // This test was introduced in API level 36, but is not version guarded because it requires a
+    // manual opt-in anyway. This makes it easier to run on older devices.
     auto error = GenerateKey(AuthorizationSetBuilder()
                                      .RsaSigningKey(2048, 65537)
                                      .Digest(Digest::NONE)
                                      .Padding(PaddingMode::NONE)
                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                     .Authorization(TAG_ROLLBACK_RESISTANCE)
                                      .SetDefaultValidity());
-    if (error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE) {
-        GTEST_SKIP() << "Rollback resistance not supported";
-    }
-
-    // Delete must work if rollback protection is implemented
     ASSERT_EQ(ErrorCode::OK, error);
-    AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
-    ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
 
     ASSERT_EQ(ErrorCode::OK, DeleteAllKeys());
 
@@ -8759,7 +8766,8 @@
 // Re-enable and run at your own risk.
 TEST_P(DestroyAttestationIdsTest, DISABLED_DestroyTest) {
     auto result = DestroyAttestationIds();
-    EXPECT_TRUE(result == ErrorCode::OK || result == ErrorCode::UNIMPLEMENTED);
+    EXPECT_TRUE(result == ErrorCode::OK || result == ErrorCode::UNIMPLEMENTED)
+            << "unexpected result " << result;
 }
 
 INSTANTIATE_KEYMINT_AIDL_TEST(DestroyAttestationIdsTest);
@@ -8892,26 +8900,84 @@
 
 INSTANTIATE_KEYMINT_AIDL_TEST(EarlyBootKeyTest);
 
+using ModuleHashTest = KeyMintAidlTestBase;
+
+TEST_P(ModuleHashTest, SetSameValue) {
+    if (AidlVersion() < 4) {
+        GTEST_SKIP() << "Module hash only available for >= v4, this device is v" << AidlVersion();
+    }
+    auto module_hash = getModuleHash();
+    ASSERT_TRUE(module_hash.has_value());
+
+    // Setting the same value that's already there should work.
+    vector<KeyParameter> info = {Authorization(TAG_MODULE_HASH, module_hash.value())};
+    EXPECT_TRUE(keymint_->setAdditionalAttestationInfo(info).isOk());
+}
+
+TEST_P(ModuleHashTest, SetDifferentValue) {
+    if (AidlVersion() < 4) {
+        GTEST_SKIP() << "Module hash only available for >= v4, this device is v" << AidlVersion();
+    }
+    auto module_hash = getModuleHash();
+    ASSERT_TRUE(module_hash.has_value());
+    vector<uint8_t> wrong_hash = module_hash.value();
+    ASSERT_EQ(wrong_hash.size(), 32);
+
+    // Setting a slightly different value should fail.
+    wrong_hash[0] ^= 0x01;
+    vector<KeyParameter> info = {Authorization(TAG_MODULE_HASH, wrong_hash)};
+    EXPECT_EQ(GetReturnErrorCode(keymint_->setAdditionalAttestationInfo(info)),
+              ErrorCode::MODULE_HASH_ALREADY_SET);
+}
+
+TEST_P(ModuleHashTest, SetUnrelatedTag) {
+    if (AidlVersion() < 4) {
+        GTEST_SKIP() << "Module hash only available for >= v4, this device is v" << AidlVersion();
+    }
+
+    // Trying to set an unexpected tag should be silently ignored..
+    vector<uint8_t> data = {0, 1, 2, 3, 4};
+    vector<KeyParameter> info = {Authorization(TAG_ROOT_OF_TRUST, data)};
+    EXPECT_EQ(GetReturnErrorCode(keymint_->setAdditionalAttestationInfo(info)), ErrorCode::OK);
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(ModuleHashTest);
+
 using VsrRequirementTest = KeyMintAidlTestBase;
 
 // @VsrTest = VSR-3.10-008
 TEST_P(VsrRequirementTest, Vsr13Test) {
-    int vsr_api_level = get_vsr_api_level();
-    if (vsr_api_level < __ANDROID_API_T__) {
-        GTEST_SKIP() << "Applies only to VSR API level 33, this device is: " << vsr_api_level;
+    int vendor_api_level = get_vendor_api_level();
+    if (vendor_api_level < __ANDROID_API_T__) {
+        GTEST_SKIP() << "Applies only to vendor API level >= 33, but this device is: "
+                     << vendor_api_level;
     }
     EXPECT_GE(AidlVersion(), 2) << "VSR 13+ requires KeyMint version 2";
 }
 
 // @VsrTest = VSR-3.10-013.001
 TEST_P(VsrRequirementTest, Vsr14Test) {
-    int vsr_api_level = get_vsr_api_level();
-    if (vsr_api_level < __ANDROID_API_U__) {
-        GTEST_SKIP() << "Applies only to VSR API level 34, this device is: " << vsr_api_level;
+    int vendor_api_level = get_vendor_api_level();
+    if (vendor_api_level < __ANDROID_API_U__) {
+        GTEST_SKIP() << "Applies only to vendor API level >= 34, but this device is: "
+                     << vendor_api_level;
     }
     EXPECT_GE(AidlVersion(), 3) << "VSR 14+ requires KeyMint version 3";
 }
 
+// @VsrTest = GMS-VSR-3.10-019
+TEST_P(VsrRequirementTest, Vsr16Test) {
+    int vendor_api_level = get_vendor_api_level();
+    if (vendor_api_level <= AVendorSupport_getVendorApiLevelOf(__ANDROID_API_V__)) {
+        GTEST_SKIP() << "Applies only to vendor API level > 202404, but this device is: "
+                     << vendor_api_level;
+    }
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Applies only to TEE KeyMint, not StrongBox KeyMint";
+    }
+    EXPECT_GE(AidlVersion(), 4) << "VSR 16+ requires KeyMint version 4 in TEE";
+}
+
 INSTANTIATE_KEYMINT_AIDL_TEST(VsrRequirementTest);
 
 class InstanceTest : public testing::Test {
diff --git a/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp b/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp
index 9f7322a..5888644 100644
--- a/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp
+++ b/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp
@@ -26,6 +26,7 @@
 #include <cppbor_parse.h>
 #include <keymaster/cppcose/cppcose.h>
 #include <keymint_support/key_param_output.h>
+#include <vendorsupport/api_level.h>
 
 #include "KeyMintAidlTestBase.h"
 
@@ -114,10 +115,23 @@
         const auto& vbKey = rot->asArray()->get(pos++);
         ASSERT_TRUE(vbKey);
         ASSERT_TRUE(vbKey->asBstr());
-        if (get_vsr_api_level() >= __ANDROID_API_V__) {
-            // The attestation should contain the SHA-256 hash of the verified boot
-            // key.  However, this not was checked for earlier versions of the KeyMint
-            // HAL so only be strict for VSR-V and above.
+        if (get_vendor_api_level() > AVendorSupport_getVendorApiLevelOf(__ANDROID_API_V__)) {
+            // The Verified Boot key field should be exactly 32 bytes since it
+            // contains the SHA-256 hash of the key on locked devices or 32 bytes
+            // of zeroes on unlocked devices. This wasn't checked for earlier
+            // versions of the KeyMint HAL, so we version-gate the strict check.
+            ASSERT_EQ(vbKey->asBstr()->value().size(), 32);
+        } else if (get_vendor_api_level() ==
+                   AVendorSupport_getVendorApiLevelOf(__ANDROID_API_V__)) {
+            // The Verified Boot key field should be:
+            //   - Exactly 32 bytes on locked devices since it should contain
+            //     the SHA-256 hash of the key, or
+            //   - Up to 32 bytes of zeroes on unlocked devices (behaviour on
+            //     unlocked devices isn't specified in the HAL interface
+            //     specification).
+            // Thus, we can't check for strict equality in case unlocked devices
+            // report values with less than 32 bytes. This wasn't checked for
+            // earlier versions of the KeyMint HAL, so we version-gate the check.
             ASSERT_LE(vbKey->asBstr()->value().size(), 32);
         }
 
diff --git a/security/keymint/aidl/vts/performance/KeyMintBenchmark.cpp b/security/keymint/aidl/vts/performance/KeyMintBenchmark.cpp
index 49fd0c9..781b7a6 100644
--- a/security/keymint/aidl/vts/performance/KeyMintBenchmark.cpp
+++ b/security/keymint/aidl/vts/performance/KeyMintBenchmark.cpp
@@ -294,6 +294,7 @@
     ErrorCode DeleteKey() {
         Status result = keymint_->deleteKey(key_blob_);
         key_blob_ = vector<uint8_t>();
+        key_transform_ = "";
         return GetReturnErrorCode(result);
     }
 
diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp
index 5c9efef..7050141 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -30,6 +30,7 @@
         "-Wall",
         "-Wextra",
         "-Werror",
+        "-DKEYMINT_HAL_V4",
     ],
     srcs: [
         "attestation_record.cpp",
@@ -40,6 +41,9 @@
     export_include_dirs: [
         "include",
     ],
+    header_libs: [
+        "libhardware_headers",
+    ],
     defaults: [
         "keymint_use_latest_hal_aidl_ndk_shared",
     ],
@@ -52,6 +56,35 @@
 }
 
 cc_library {
+    name: "libkeymint_support_V3",
+    vendor_available: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    srcs: [
+        "attestation_record.cpp",
+        "authorization_set.cpp",
+        "keymint_utils.cpp",
+        "key_param_output.cpp",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+    header_libs: [
+        "libhardware_headers",
+    ],
+    shared_libs: [
+        "android.hardware.security.keymint-V3-ndk",
+        "libbase",
+        "libcrypto",
+        "libutils",
+        "libhardware",
+    ],
+}
+
+cc_library {
     name: "libkeymint_remote_prov_support",
     vendor_available: true,
     srcs: [
@@ -82,6 +115,7 @@
 
 cc_test {
     name: "libkeymint_remote_prov_support_test",
+    cpp_std: "c++20",
     srcs: ["remote_prov_utils_test.cpp"],
     static_libs: [
         "android.hardware.security.rkp-V3-ndk",
@@ -94,6 +128,7 @@
     ],
     shared_libs: [
         "libbase",
+        "libbinder_ndk",
         "libcppbor",
         "libcppcose_rkp",
         "libcrypto",
diff --git a/security/keymint/support/attestation_record.cpp b/security/keymint/support/attestation_record.cpp
index 5a26611..d2cbf88 100644
--- a/security/keymint/support/attestation_record.cpp
+++ b/security/keymint/support/attestation_record.cpp
@@ -106,6 +106,7 @@
     ASN1_NULL* device_unique_attestation;
     ASN1_NULL* identity_credential;
     ASN1_OCTET_STRING* attestation_id_second_imei;
+    ASN1_OCTET_STRING* module_hash;
 } KM_AUTH_LIST;
 
 ASN1_SEQUENCE(KM_AUTH_LIST) = {
@@ -173,6 +174,7 @@
                      TAG_IDENTITY_CREDENTIAL_KEY.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_second_imei, ASN1_OCTET_STRING,
                      TAG_ATTESTATION_ID_SECOND_IMEI.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, module_hash, ASN1_OCTET_STRING, TAG_MODULE_HASH.maskedTag()),
 } ASN1_SEQUENCE_END(KM_AUTH_LIST);
 IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
 
@@ -327,6 +329,7 @@
     copyAuthTag(record->device_unique_attestation, TAG_DEVICE_UNIQUE_ATTESTATION, auth_list);
     copyAuthTag(record->identity_credential, TAG_IDENTITY_CREDENTIAL_KEY, auth_list);
     copyAuthTag(record->attestation_id_second_imei, TAG_ATTESTATION_ID_SECOND_IMEI, auth_list);
+    copyAuthTag(record->module_hash, TAG_MODULE_HASH, auth_list);
 
     return ErrorCode::OK;
 }
diff --git a/security/keymint/support/fuzzer/keymint_attestation_fuzzer.cpp b/security/keymint/support/fuzzer/keymint_attestation_fuzzer.cpp
index bd781ac..1757997 100644
--- a/security/keymint/support/fuzzer/keymint_attestation_fuzzer.cpp
+++ b/security/keymint/support/fuzzer/keymint_attestation_fuzzer.cpp
@@ -151,7 +151,7 @@
 
 extern "C" int LLVMFuzzerInitialize(int /* *argc */, char /* ***argv */) {
     ::ndk::SpAIBinder binder(AServiceManager_waitForService(kServiceName.c_str()));
-    gKeyMint = std::move(IKeyMintDevice::fromBinder(binder));
+    gKeyMint = IKeyMintDevice::fromBinder(binder);
     LOG_ALWAYS_FATAL_IF(!gKeyMint, "Failed to get IKeyMintDevice instance.");
     return 0;
 }
diff --git a/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp b/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp
index 6bd986c..ebccf25 100644
--- a/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp
+++ b/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp
@@ -74,14 +74,22 @@
     uint8_t challengeSize = mFdp.ConsumeIntegralInRange<uint8_t>(kMinSize, kChallengeSize);
     std::vector<uint8_t> challenge = mFdp.ConsumeBytes<uint8_t>(challengeSize);
 
+    RpcHardwareInfo rpcHardwareInfo;
+    gRPC->getHardwareInfo(&rpcHardwareInfo);
+
     std::vector<uint8_t> csr;
     gRPC->generateCertificateRequestV2(keysToSign, challenge, &csr);
 
     while (mFdp.remaining_bytes()) {
         auto invokeProvAPI = mFdp.PickValueInArray<const std::function<void()>>({
-                [&]() { verifyFactoryCsr(cborKeysToSign, csr, gRPC.get(), challenge); },
-                [&]() { verifyProductionCsr(cborKeysToSign, csr, gRPC.get(), challenge); },
-                [&]() { isCsrWithProperDiceChain(csr); },
+                [&]() {
+                    verifyFactoryCsr(cborKeysToSign, csr, rpcHardwareInfo, kServiceName, challenge);
+                },
+                [&]() {
+                    verifyProductionCsr(cborKeysToSign, csr, rpcHardwareInfo, kServiceName,
+                                        challenge);
+                },
+                [&]() { isCsrWithProperDiceChain(csr, kServiceName); },
         });
         invokeProvAPI();
     }
diff --git a/security/keymint/support/include/keymint_support/keymint_tags.h b/security/keymint/support/include/keymint_support/keymint_tags.h
index 823899a..89c9c0b 100644
--- a/security/keymint/support/include/keymint_support/keymint_tags.h
+++ b/security/keymint/support/include/keymint_support/keymint_tags.h
@@ -103,6 +103,15 @@
 DECLARE_TYPED_TAG(MAX_USES_PER_BOOT);
 DECLARE_TYPED_TAG(MIN_MAC_LENGTH);
 DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS);
+// TODO: remove special case macro once v4 HAL is frozen
+#ifdef KEYMINT_HAL_V4
+DECLARE_TYPED_TAG(MODULE_HASH);
+#else
+// When building for previous frozen HAL, the `Tag::MODULE_NAME` constant is not available.
+static const Tag Tag_MODULE_HASH = static_cast<Tag>(-1879047468);
+typedef typename Tag2TypedTag<Tag_MODULE_HASH>::type TAG_MODULE_HASH_t;
+static TAG_MODULE_HASH_t TAG_MODULE_HASH;
+#endif
 DECLARE_TYPED_TAG(NONCE);
 DECLARE_TYPED_TAG(NO_AUTH_REQUIRED);
 DECLARE_TYPED_TAG(ORIGIN);
diff --git a/security/keymint/support/include/remote_prov/remote_prov_utils.h b/security/keymint/support/include/remote_prov/remote_prov_utils.h
index 1d7db6a..4e0ce29 100644
--- a/security/keymint/support/include/remote_prov/remote_prov_utils.h
+++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h
@@ -21,6 +21,7 @@
 #include <vector>
 #include "aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h"
 
+#include <hwtrust/hwtrust.h>
 #include <keymaster/cppcose/cppcose.h>
 
 namespace aidl::android::hardware::security::keymint::remote_prov {
@@ -28,6 +29,11 @@
 using bytevec = std::vector<uint8_t>;
 using namespace cppcose;
 
+constexpr std::string_view kErrorChallengeMismatch = "challenges do not match";
+constexpr std::string_view kErrorUdsCertsAreRequired = "UdsCerts are required";
+constexpr std::string_view kErrorKeysToSignMismatch = "KeysToSign do not match";
+constexpr std::string_view kErrorDiceChainIsDegenerate = "DICE chain is degenerate";
+
 extern bytevec kTestMacKey;
 
 // The Google root key for the Endpoint Encryption Key chain, encoded as COSE_Sign1
@@ -88,6 +94,18 @@
  */
 bytevec randomBytes(size_t numBytes);
 
+const std::string DEFAULT_INSTANCE_NAME =
+        "android.hardware.security.keymint.IRemotelyProvisionedComponent/default";
+const std::string RKPVM_INSTANCE_NAME =
+        "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf";
+
+/**
+ * Returns the portion of an instance name after the /
+ * e.g. for "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf",
+ * it returns "avf".
+ */
+std::string_view deviceSuffix(std::string_view name);
+
 struct EekChain {
     bytevec chain;
     bytevec last_pubkey;
@@ -140,7 +158,7 @@
  * is parsed in the manufacturing process.
  */
 ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateFactoryDeviceInfo(
-        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable);
+        const std::vector<uint8_t>& deviceInfoBytes, const RpcHardwareInfo& info);
 
 /**
  * Parses a DeviceInfo structure from the given CBOR data. The parsed data is then validated to
@@ -149,7 +167,7 @@
  * suitable for the end user.
  */
 ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateProductionDeviceInfo(
-        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable);
+        const std::vector<uint8_t>& deviceInfoBytes, const RpcHardwareInfo& info);
 
 /**
  * Verify the protected data as if the device is still early in the factory process and may not
@@ -158,32 +176,65 @@
 ErrMsgOr<std::vector<BccEntryData>> verifyFactoryProtectedData(
         const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
         const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
-        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId, const RpcHardwareInfo& info,
+        const std::string& instanceName, const std::vector<uint8_t>& challenge);
 /**
  * Verify the protected data as if the device is a final production sample.
  */
 ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData(
         const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
         const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
-        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId, const RpcHardwareInfo& info,
+        const std::string& instanceName, const std::vector<uint8_t>& challenge,
+        bool allowAnyMode = false);
 
 /**
  * Verify the CSR as if the device is still early in the factory process and may not
  * have all device identifiers provisioned yet.
  */
-ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
-        const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(const cppbor::Array& keysToSign,
+                                                          const std::vector<uint8_t>& csr,
+                                                          const RpcHardwareInfo& info,
+                                                          const std::string& instanceName,
+                                                          const std::vector<uint8_t>& challenge,
+                                                          bool allowDegenerate = true,
+                                                          bool requireUdsCerts = false);
+
 /**
  * Verify the CSR as if the device is a final production sample.
  */
-ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(
-        const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(const cppbor::Array& keysToSign,
+                                                             const std::vector<uint8_t>& csr,
+                                                             const RpcHardwareInfo& info,
+                                                             const std::string& instanceName,
+                                                             const std::vector<uint8_t>& challenge,
+                                                             bool allowAnyMode = false);
 
 /** Checks whether the CSR has a proper DICE chain. */
-ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr);
+ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr,
+                                        const std::string& instanceName);
+
+/** Checks whether the CSRs contain DICE certificate chains that have root certificates
+ * with the same public key.
+ */
+ErrMsgOr<bool> compareRootPublicKeysInDiceChains(const std::vector<uint8_t>& csr1,
+                                                 std::string_view instanceName1,
+                                                 const std::vector<uint8_t>& csr2,
+                                                 std::string_view instanceName2);
+
+/** Checks whether the component name in the configuration descriptor in the leaf certificate
+ * of the primary KeyMint instance's DICE certificate chain contains "keymint"
+ */
+ErrMsgOr<bool> verifyComponentNameInKeyMintDiceChain(const std::vector<uint8_t>& csr);
+
+/** Checks whether the DICE chain in the CSR has a certificate with a non-normal mode. */
+ErrMsgOr<bool> hasNonNormalModeInDiceChain(const std::vector<uint8_t>& csr,
+                                           std::string_view instanceName);
+
+/** Verify the DICE chain. */
+ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc,
+                                                hwtrust::DiceChain::Kind kind, bool allowAnyMode,
+                                                bool allowDegenerate,
+                                                const std::string& instanceName);
 
 }  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index d426919..ecf69e8 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <format>
 #include <iomanip>
 #include <iterator>
 #include <memory>
@@ -26,7 +27,6 @@
 #include <android-base/macros.h>
 #include <android-base/properties.h>
 #include <cppbor.h>
-#include <hwtrust/hwtrust.h>
 #include <json/json.h>
 #include <keymaster/km_openssl/ec_key.h>
 #include <keymaster/km_openssl/ecdsa_operation.h>
@@ -46,6 +46,7 @@
 constexpr int32_t kBccPayloadKeyUsage = -4670553;
 constexpr int kP256AffinePointSize = 32;
 constexpr uint32_t kNumTeeDeviceInfoEntries = 14;
+constexpr std::string_view kKeyMintComponentName = "keymint";
 
 using EC_KEY_Ptr = bssl::UniquePtr<EC_KEY>;
 using EVP_PKEY_Ptr = bssl::UniquePtr<EVP_PKEY>;
@@ -53,6 +54,14 @@
 using X509_Ptr = bssl::UniquePtr<X509>;
 using CRYPTO_BUFFER_Ptr = bssl::UniquePtr<CRYPTO_BUFFER>;
 
+std::string_view deviceSuffix(std::string_view name) {
+    auto pos = name.rfind('/');
+    if (pos == std::string::npos) {
+        return name;
+    }
+    return name.substr(pos + 1);
+}
+
 ErrMsgOr<bytevec> ecKeyGetPrivateKey(const EC_KEY* ecKey) {
     // Extract private key.
     const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey);
@@ -116,37 +125,6 @@
     return std::make_tuple(std::move(pubX), std::move(pubY));
 }
 
-ErrMsgOr<bytevec> getRawPublicKey(const EVP_PKEY_Ptr& pubKey) {
-    if (pubKey.get() == nullptr) {
-        return "pkey is null.";
-    }
-    int keyType = EVP_PKEY_base_id(pubKey.get());
-    switch (keyType) {
-        case EVP_PKEY_EC: {
-            int nid = EVP_PKEY_bits(pubKey.get()) == 384 ? NID_secp384r1 : NID_X9_62_prime256v1;
-            auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pubKey.get()));
-            if (ecKey.get() == nullptr) {
-                return "Failed to get ec key";
-          }
-          return ecKeyGetPublicKey(ecKey.get(), nid);
-        }
-        case EVP_PKEY_ED25519: {
-            bytevec rawPubKey;
-            size_t rawKeySize = 0;
-            if (!EVP_PKEY_get_raw_public_key(pubKey.get(), NULL, &rawKeySize)) {
-                return "Failed to get raw public key.";
-            }
-            rawPubKey.resize(rawKeySize);
-            if (!EVP_PKEY_get_raw_public_key(pubKey.get(), rawPubKey.data(), &rawKeySize)) {
-                return "Failed to get raw public key.";
-            }
-            return rawPubKey;
-        }
-        default:
-            return "Unknown key type.";
-    }
-}
-
 ErrMsgOr<std::tuple<bytevec, bytevec>> generateEc256KeyPair() {
     auto ec_key = EC_KEY_Ptr(EC_KEY_new());
     if (ec_key.get() == nullptr) {
@@ -159,7 +137,7 @@
     }
 
     if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
-        EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
+        EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) != 1) {
         return "Error generating key";
     }
 
@@ -324,13 +302,36 @@
     return chain.encode();
 }
 
+bool maybeOverrideAllowAnyMode(bool allowAnyMode) {
+    // Use ro.build.type instead of ro.debuggable because ro.debuggable=1 for VTS testing
+    std::string build_type = ::android::base::GetProperty("ro.build.type", "");
+    if (!build_type.empty() && build_type != "user") {
+        return true;
+    }
+    return allowAnyMode;
+}
+
 ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc,
-                                                hwtrust::DiceChain::Kind kind) {
+                                                hwtrust::DiceChain::Kind kind, bool allowAnyMode,
+                                                bool allowDegenerate,
+                                                const std::string& instanceName) {
     auto encodedBcc = bcc->encode();
-    auto chain = hwtrust::DiceChain::Verify(encodedBcc, kind);
-    if (!chain.ok()) return chain.error().message();
+
+    allowAnyMode = maybeOverrideAllowAnyMode(allowAnyMode);
+
+    auto chain =
+            hwtrust::DiceChain::Verify(encodedBcc, kind, allowAnyMode, deviceSuffix(instanceName));
+    if (!chain.ok()) {
+        return chain.error().message();
+    }
+    if (!allowDegenerate && !chain->IsProper()) {
+        return "DICE chain is degenerate";
+    }
+
     auto keys = chain->CosePublicKeys();
-    if (!keys.ok()) return keys.error().message();
+    if (!keys.ok()) {
+        return keys.error().message();
+    }
     std::vector<BccEntryData> result;
     for (auto& key : *keys) {
         result.push_back({std::move(key)});
@@ -458,7 +459,7 @@
 }
 
 ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
-        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable,
+        const std::vector<uint8_t>& deviceInfoBytes, const RpcHardwareInfo& rpcHardwareInfo,
         bool isFactory) {
     const cppbor::Array kValidVbStates = {"green", "yellow", "orange"};
     const cppbor::Array kValidBootloaderStates = {"locked", "unlocked"};
@@ -505,9 +506,7 @@
         return "DeviceInfo ordering is non-canonical.";
     }
 
-    RpcHardwareInfo info;
-    provisionable->getHardwareInfo(&info);
-    if (info.versionNumber < 3) {
+    if (rpcHardwareInfo.versionNumber < 3) {
         const std::unique_ptr<cppbor::Item>& version = parsed->get("version");
         if (!version) {
             return "Device info is missing version";
@@ -515,10 +514,10 @@
         if (!version->asUint()) {
             return "version must be an unsigned integer";
         }
-        if (version->asUint()->value() != info.versionNumber) {
+        if (version->asUint()->value() != rpcHardwareInfo.versionNumber) {
             return "DeviceInfo version (" + std::to_string(version->asUint()->value()) +
                    ") does not match the remotely provisioned component version (" +
-                   std::to_string(info.versionNumber) + ").";
+                   std::to_string(rpcHardwareInfo.versionNumber) + ").";
         }
     }
     // Bypasses the device info validation since the device info in AVF is currently
@@ -527,17 +526,17 @@
     // TODO(b/300911665): This check is temporary and will be replaced once the markers
     // on the DICE chain become available. We need to determine if the CSR is from the
     // RKP VM using the markers on the DICE chain.
-    if (info.uniqueId == "AVF Remote Provisioning 1") {
+    if (rpcHardwareInfo.uniqueId == "AVF Remote Provisioning 1") {
         return std::move(parsed);
     }
 
     std::string error;
     std::string tmp;
     std::set<std::string_view> previousKeys;
-    switch (info.versionNumber) {
+    switch (rpcHardwareInfo.versionNumber) {
         case 3:
             if (isTeeDeviceInfo(*parsed) && parsed->size() != kNumTeeDeviceInfoEntries) {
-                error += fmt::format(
+                error += std::format(
                         "Err: Incorrect number of device info entries. Expected {} but got "
                         "{}\n",
                         kNumTeeDeviceInfoEntries, parsed->size());
@@ -546,7 +545,7 @@
             // may omit `os_version`
             if (!isTeeDeviceInfo(*parsed) && (parsed->size() != kNumTeeDeviceInfoEntries &&
                                               parsed->size() != kNumTeeDeviceInfoEntries - 1)) {
-                error += fmt::format(
+                error += std::format(
                         "Err: Incorrect number of device info entries. Expected {} or {} but got "
                         "{}\n",
                         kNumTeeDeviceInfoEntries - 1, kNumTeeDeviceInfoEntries, parsed->size());
@@ -601,7 +600,7 @@
                                    kValidAttIdStates);
             break;
         default:
-            return "Unrecognized version: " + std::to_string(info.versionNumber);
+            return "Unrecognized version: " + std::to_string(rpcHardwareInfo.versionNumber);
     }
 
     if (!error.empty()) {
@@ -612,13 +611,13 @@
 }
 
 ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateFactoryDeviceInfo(
-        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable) {
-    return parseAndValidateDeviceInfo(deviceInfoBytes, provisionable, /*isFactory=*/true);
+        const std::vector<uint8_t>& deviceInfoBytes, const RpcHardwareInfo& rpcHardwareInfo) {
+    return parseAndValidateDeviceInfo(deviceInfoBytes, rpcHardwareInfo, /*isFactory=*/true);
 }
 
 ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateProductionDeviceInfo(
-        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable) {
-    return parseAndValidateDeviceInfo(deviceInfoBytes, provisionable, /*isFactory=*/false);
+        const std::vector<uint8_t>& deviceInfoBytes, const RpcHardwareInfo& rpcHardwareInfo) {
+    return parseAndValidateDeviceInfo(deviceInfoBytes, rpcHardwareInfo, /*isFactory=*/false);
 }
 
 ErrMsgOr<bytevec> getSessionKey(ErrMsgOr<std::pair<bytevec, bytevec>>& senderPubkey,
@@ -636,9 +635,9 @@
 ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData(
         const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
         const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
-        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
-        bool isFactory) {
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId,
+        const RpcHardwareInfo& rpcHardwareInfo, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge, bool isFactory, bool allowAnyMode = false) {
     auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
     if (!parsedProtectedData) {
         return protDataErrMsg;
@@ -660,7 +659,7 @@
         return "The COSE_encrypt recipient does not match the expected EEK identifier";
     }
 
-    auto sessionKey = getSessionKey(senderPubkey, eekChain, supportedEekCurve);
+    auto sessionKey = getSessionKey(senderPubkey, eekChain, rpcHardwareInfo.supportedEekCurve);
     if (!sessionKey) {
         return sessionKey.message();
     }
@@ -694,13 +693,14 @@
     }
 
     // BCC is [ pubkey, + BccEntry]
-    auto bccContents = validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr13);
+    auto bccContents = validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr13, allowAnyMode,
+                                   /*allowDegenerate=*/true, instanceName);
     if (!bccContents) {
         return bccContents.message() + "\n" + prettyPrint(bcc.get());
     }
 
     auto deviceInfoResult =
-            parseAndValidateDeviceInfo(deviceInfo.deviceInfo, provisionable, isFactory);
+            parseAndValidateDeviceInfo(deviceInfo.deviceInfo, rpcHardwareInfo, isFactory);
     if (!deviceInfoResult) {
         return deviceInfoResult.message();
     }
@@ -736,240 +736,23 @@
 ErrMsgOr<std::vector<BccEntryData>> verifyFactoryProtectedData(
         const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
         const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
-        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId,
+        const RpcHardwareInfo& rpcHardwareInfo, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge) {
     return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
-                               eekId, supportedEekCurve, provisionable, challenge,
+                               eekId, rpcHardwareInfo, instanceName, challenge,
                                /*isFactory=*/true);
 }
 
 ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData(
         const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
         const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
-        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId,
+        const RpcHardwareInfo& rpcHardwareInfo, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge, bool allowAnyMode) {
     return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
-                               eekId, supportedEekCurve, provisionable, challenge,
-                               /*isFactory=*/false);
-}
-
-ErrMsgOr<X509_Ptr> parseX509Cert(const std::vector<uint8_t>& cert) {
-    CRYPTO_BUFFER_Ptr certBuf(CRYPTO_BUFFER_new(cert.data(), cert.size(), nullptr));
-    if (!certBuf.get()) {
-        return "Failed to create crypto buffer.";
-    }
-    X509_Ptr result(X509_parse_from_buffer(certBuf.get()));
-    if (!result.get()) {
-        return "Failed to parse certificate.";
-    }
-    return result;
-}
-
-std::string getX509IssuerName(const X509_Ptr& cert) {
-    char* name = X509_NAME_oneline(X509_get_issuer_name(cert.get()), nullptr, 0);
-    std::string result(name);
-    OPENSSL_free(name);
-    return result;
-}
-
-std::string getX509SubjectName(const X509_Ptr& cert) {
-    char* name = X509_NAME_oneline(X509_get_subject_name(cert.get()), nullptr, 0);
-    std::string result(name);
-    OPENSSL_free(name);
-    return result;
-}
-
-// Validates the certificate chain and returns the leaf public key.
-ErrMsgOr<bytevec> validateCertChain(const cppbor::Array& chain) {
-    bytevec rawPubKey;
-    for (size_t i = 0; i < chain.size(); ++i) {
-        // Root must be self-signed.
-        size_t signingCertIndex = (i > 0) ? i - 1 : i;
-        auto& keyCertItem = chain[i];
-        auto& signingCertItem = chain[signingCertIndex];
-        if (!keyCertItem || !keyCertItem->asBstr()) {
-            return "Key certificate must be a Bstr.";
-        }
-        if (!signingCertItem || !signingCertItem->asBstr()) {
-            return "Signing certificate must be a Bstr.";
-        }
-
-        auto keyCert = parseX509Cert(keyCertItem->asBstr()->value());
-        if (!keyCert) {
-            return keyCert.message();
-        }
-        auto signingCert = parseX509Cert(signingCertItem->asBstr()->value());
-        if (!signingCert) {
-            return signingCert.message();
-        }
-
-        EVP_PKEY_Ptr pubKey(X509_get_pubkey(keyCert->get()));
-        if (!pubKey.get()) {
-            return "Failed to get public key.";
-        }
-        EVP_PKEY_Ptr signingPubKey(X509_get_pubkey(signingCert->get()));
-        if (!signingPubKey.get()) {
-            return "Failed to get signing public key.";
-        }
-
-        if (!X509_verify(keyCert->get(), signingPubKey.get())) {
-            return "Verification of certificate " + std::to_string(i) +
-                   " faile. OpenSSL error string: " + ERR_error_string(ERR_get_error(), NULL);
-        }
-
-        auto certIssuer = getX509IssuerName(*keyCert);
-        auto signerSubj = getX509SubjectName(*signingCert);
-        if (certIssuer != signerSubj) {
-            return "Certificate " + std::to_string(i) + " has wrong issuer. Signer subject is " +
-                   signerSubj + " Issuer subject is " + certIssuer;
-        }
-        if (i == chain.size() - 1) {
-            auto key = getRawPublicKey(pubKey);
-            if (!key) return key.moveMessage();
-            rawPubKey = key.moveValue();
-        }
-    }
-    return rawPubKey;
-}
-
-std::string validateUdsCerts(const cppbor::Map& udsCerts, const bytevec& udsCoseKeyBytes) {
-    for (const auto& [signerName, udsCertChain] : udsCerts) {
-        if (!signerName || !signerName->asTstr()) {
-            return "Signer Name must be a Tstr.";
-        }
-        if (!udsCertChain || !udsCertChain->asArray()) {
-            return "UDS certificate chain must be an Array.";
-        }
-        if (udsCertChain->asArray()->size() < 2) {
-            return "UDS certificate chain must have at least two entries: root and leaf.";
-        }
-
-        auto leafPubKey = validateCertChain(*udsCertChain->asArray());
-        if (!leafPubKey) {
-            return leafPubKey.message();
-        }
-        auto coseKey = CoseKey::parse(udsCoseKeyBytes);
-        if (!coseKey) return coseKey.moveMessage();
-
-        auto curve = coseKey->getIntValue(CoseKey::CURVE);
-        if (!curve) {
-            return "CoseKey must contain curve.";
-        }
-        bytevec udsPub;
-        if (curve == CoseKeyCurve::P256 || curve == CoseKeyCurve::P384) {
-            auto pubKey = coseKey->getEcPublicKey();
-            if (!pubKey) return pubKey.moveMessage();
-            // convert public key to uncompressed form by prepending 0x04 at begin.
-            pubKey->insert(pubKey->begin(), 0x04);
-            udsPub = pubKey.moveValue();
-        } else if (curve == CoseKeyCurve::ED25519) {
-            auto& pubkey = coseKey->getMap().get(cppcose::CoseKey::PUBKEY_X);
-            if (!pubkey || !pubkey->asBstr()) {
-                return "Invalid public key.";
-            }
-            udsPub = pubkey->asBstr()->value();
-        } else {
-            return "Unknown curve.";
-        }
-        if (*leafPubKey != udsPub) {
-            return "Leaf public key in UDS certificate chain doesn't match UDS public key.";
-        }
-    }
-    return "";
-}
-
-ErrMsgOr<std::unique_ptr<cppbor::Array>> parseAndValidateCsrPayload(
-        const cppbor::Array& keysToSign, const std::vector<uint8_t>& csrPayload,
-        IRemotelyProvisionedComponent* provisionable, bool isFactory) {
-    auto [parsedCsrPayload, _, errMsg] = cppbor::parse(csrPayload);
-    if (!parsedCsrPayload) {
-        return errMsg;
-    }
-
-    std::unique_ptr<cppbor::Array> parsed(parsedCsrPayload.release()->asArray());
-    if (!parsed) {
-        return "CSR payload is not a CBOR array.";
-    }
-
-    if (parsed->size() != 4U) {
-        return "CSR payload must contain version, certificate type, device info, keys. "
-               "However, the parsed CSR payload has " +
-               std::to_string(parsed->size()) + " entries.";
-    }
-
-    auto signedVersion = parsed->get(0)->asUint();
-    auto signedCertificateType = parsed->get(1)->asTstr();
-    auto signedDeviceInfo = parsed->get(2)->asMap();
-    auto signedKeys = parsed->get(3)->asArray();
-
-    if (!signedVersion || signedVersion->value() != 3U) {
-        return "CSR payload version must be an unsigned integer and must be equal to 3.";
-    }
-    if (!signedCertificateType) {
-        // Certificate type is allowed to be extendend by vendor, i.e. we can't
-        // enforce its value.
-        return "Certificate type must be a Tstr.";
-    }
-    if (!signedDeviceInfo) {
-        return "Device info must be an Map.";
-    }
-    if (!signedKeys) {
-        return "Keys must be an Array.";
-    }
-
-    auto result = parseAndValidateDeviceInfo(signedDeviceInfo->encode(), provisionable, isFactory);
-    if (!result) {
-        return result.message();
-    }
-
-    if (signedKeys->encode() != keysToSign.encode()) {
-        return "Signed keys do not match.";
-    }
-
-    return std::move(parsed);
-}
-
-ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequestSignedPayload(
-        const std::vector<uint8_t>& signedPayload, const std::vector<uint8_t>& challenge) {
-    auto [parsedSignedPayload, _, errMsg] = cppbor::parse(signedPayload);
-    if (!parsedSignedPayload) {
-        return errMsg;
-    }
-    if (!parsedSignedPayload->asArray()) {
-        return "SignedData payload is not a CBOR array.";
-    }
-    if (parsedSignedPayload->asArray()->size() != 2U) {
-        return "SignedData payload must contain the challenge and request. However, the parsed "
-               "SignedData payload has " +
-               std::to_string(parsedSignedPayload->asArray()->size()) + " entries.";
-    }
-
-    auto signedChallenge = parsedSignedPayload->asArray()->get(0)->asBstr();
-    auto signedRequest = parsedSignedPayload->asArray()->get(1)->asBstr();
-
-    if (!signedChallenge) {
-        return "Challenge must be a Bstr.";
-    }
-
-    if (challenge.size() > 64) {
-        return "Challenge size must be between 0 and 64 bytes inclusive. "
-               "However, challenge is " +
-               std::to_string(challenge.size()) + " bytes long.";
-    }
-
-    auto challengeBstr = cppbor::Bstr(challenge);
-    if (*signedChallenge != challengeBstr) {
-        return "Signed challenge does not match."
-               "\n  Actual: " +
-               cppbor::prettyPrint(signedChallenge->asBstr(), 64 /* maxBStrSize */) +
-               "\nExpected: " + cppbor::prettyPrint(&challengeBstr, 64 /* maxBStrSize */);
-    }
-
-    if (!signedRequest) {
-        return "Request must be a Bstr.";
-    }
-
-    return signedRequest->value();
+                               eekId, rpcHardwareInfo, instanceName, challenge,
+                               /*isFactory=*/false, allowAnyMode);
 }
 
 ErrMsgOr<hwtrust::DiceChain::Kind> getDiceChainKind() {
@@ -980,141 +763,213 @@
         return hwtrust::DiceChain::Kind::kVsr14;
     } else if (vendor_api_level == 202404) {
         return hwtrust::DiceChain::Kind::kVsr15;
+    } else if (vendor_api_level > 202404) {
+        return hwtrust::DiceChain::Kind::kVsr16;
     } else {
         return "Unsupported vendor API level: " + std::to_string(vendor_api_level);
     }
 }
 
-ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequest(const std::vector<uint8_t>& request,
-                                                       const std::vector<uint8_t>& challenge) {
-    auto [parsedRequest, _, csrErrMsg] = cppbor::parse(request);
-    if (!parsedRequest) {
-        return csrErrMsg;
-    }
-    if (!parsedRequest->asArray()) {
-        return "AuthenticatedRequest is not a CBOR array.";
-    }
-    if (parsedRequest->asArray()->size() != 4U) {
-        return "AuthenticatedRequest must contain version, UDS certificates, DICE chain, and "
-               "signed data. However, the parsed AuthenticatedRequest has " +
-               std::to_string(parsedRequest->asArray()->size()) + " entries.";
+ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(
+        const cppbor::Array& keysToSign, const std::vector<uint8_t>& encodedCsr,
+        const RpcHardwareInfo& rpcHardwareInfo, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge, bool isFactory, bool allowAnyMode = false,
+        bool allowDegenerate = true, bool requireUdsCerts = false) {
+    if (rpcHardwareInfo.versionNumber != 3) {
+        return "Remotely provisioned component version (" +
+               std::to_string(rpcHardwareInfo.versionNumber) +
+               ") does not match expected version (3).";
     }
 
-    auto version = parsedRequest->asArray()->get(0)->asUint();
-    auto udsCerts = parsedRequest->asArray()->get(1)->asMap();
-    auto diceCertChain = parsedRequest->asArray()->get(2)->asArray();
-    auto signedData = parsedRequest->asArray()->get(3)->asArray();
-
-    if (!version || version->value() != 1U) {
-        return "AuthenticatedRequest version must be an unsigned integer and must be equal to 1.";
-    }
-    if (!udsCerts) {
-        return "AuthenticatedRequest UdsCerts must be an Map.";
-    }
-    if (!diceCertChain) {
-        return "AuthenticatedRequest DiceCertChain must be an Array.";
-    }
-    if (!signedData) {
-        return "AuthenticatedRequest SignedData must be an Array.";
-    }
-
-    // DICE chain is [ pubkey, + DiceChainEntry ].
     auto diceChainKind = getDiceChainKind();
     if (!diceChainKind) {
         return diceChainKind.message();
     }
 
-    auto diceContents = validateBcc(diceCertChain, *diceChainKind);
-    if (!diceContents) {
-        return diceContents.message() + "\n" + prettyPrint(diceCertChain);
+    allowAnyMode = maybeOverrideAllowAnyMode(allowAnyMode);
+
+    auto csr = hwtrust::Csr::validate(encodedCsr, *diceChainKind, isFactory, allowAnyMode,
+                                      deviceSuffix(instanceName));
+
+    if (!csr.ok()) {
+        return csr.error().message();
     }
 
-    auto& udsPub = diceContents->back().pubKey;
+    if (!allowDegenerate) {
+        auto diceChain = csr->getDiceChain();
+        if (!diceChain.ok()) {
+            return diceChain.error().message();
+        }
 
-    auto error = validateUdsCerts(*udsCerts, udsPub);
-    if (!error.empty()) {
-        return error;
+        if (!diceChain->IsProper()) {
+            return kErrorDiceChainIsDegenerate;
+        }
     }
 
-    auto signedPayload = verifyAndParseCoseSign1(signedData, udsPub, {} /* aad */);
-    if (!signedPayload) {
-        return signedPayload.message();
+    if (requireUdsCerts && !csr->hasUdsCerts()) {
+        return kErrorUdsCertsAreRequired;
     }
 
-    auto payload = parseAndValidateAuthenticatedRequestSignedPayload(*signedPayload, challenge);
-    if (!payload) {
-        return payload.message();
+    auto equalChallenges = csr->compareChallenge(challenge);
+    if (!equalChallenges.ok()) {
+        return equalChallenges.error().message();
     }
 
-    return payload;
-}
-
-ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(const cppbor::Array& keysToSign,
-                                                   const std::vector<uint8_t>& csr,
-                                                   IRemotelyProvisionedComponent* provisionable,
-                                                   const std::vector<uint8_t>& challenge,
-                                                   bool isFactory) {
-    RpcHardwareInfo info;
-    provisionable->getHardwareInfo(&info);
-    if (info.versionNumber != 3) {
-        return "Remotely provisioned component version (" + std::to_string(info.versionNumber) +
-               ") does not match expected version (3).";
+    if (!*equalChallenges) {
+        return kErrorChallengeMismatch;
     }
 
-    auto csrPayload = parseAndValidateAuthenticatedRequest(csr, challenge);
+    auto equalKeysToSign = csr->compareKeysToSign(keysToSign.encode());
+    if (!equalKeysToSign.ok()) {
+        return equalKeysToSign.error().message();
+    }
+
+    if (!*equalKeysToSign) {
+        return kErrorKeysToSignMismatch;
+    }
+
+    auto csrPayload = csr->getCsrPayload();
     if (!csrPayload) {
-        return csrPayload.message();
+        return csrPayload.error().message();
     }
 
-    return parseAndValidateCsrPayload(keysToSign, *csrPayload, provisionable, isFactory);
+    auto [csrPayloadDecoded, _, errMsg] = cppbor::parse(*csrPayload);
+    if (!csrPayloadDecoded) {
+        return errMsg;
+    }
+
+    if (!csrPayloadDecoded->asArray()) {
+        return "CSR payload is not an array.";
+    }
+
+    return std::unique_ptr<cppbor::Array>(csrPayloadDecoded.release()->asArray());
 }
 
 ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
         const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
-    return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/true);
+        const RpcHardwareInfo& rpcHardwareInfo, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge, bool allowDegenerate, bool requireUdsCerts) {
+    return verifyCsr(keysToSign, csr, rpcHardwareInfo, instanceName, challenge, /*isFactory=*/true,
+                     /*allowAnyMode=*/false, allowDegenerate, requireUdsCerts);
 }
 
-ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(
-        const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
-    return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/false);
+ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(const cppbor::Array& keysToSign,
+                                                             const std::vector<uint8_t>& csr,
+                                                             const RpcHardwareInfo& rpcHardwareInfo,
+                                                             const std::string& instanceName,
+                                                             const std::vector<uint8_t>& challenge,
+                                                             bool allowAnyMode) {
+    return verifyCsr(keysToSign, csr, rpcHardwareInfo, instanceName, challenge, /*isFactory=*/false,
+                     allowAnyMode);
 }
 
-ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr) {
-    auto [parsedRequest, _, csrErrMsg] = cppbor::parse(csr);
-    if (!parsedRequest) {
-        return csrErrMsg;
-    }
-    if (!parsedRequest->asArray()) {
-        return "AuthenticatedRequest is not a CBOR array.";
-    }
-    if (parsedRequest->asArray()->size() != 4U) {
-        return "AuthenticatedRequest must contain version, UDS certificates, DICE chain, and "
-               "signed data. However, the parsed AuthenticatedRequest has " +
-               std::to_string(parsedRequest->asArray()->size()) + " entries.";
-    }
-
-    auto version = parsedRequest->asArray()->get(0)->asUint();
-    auto diceCertChain = parsedRequest->asArray()->get(2)->asArray();
-
-    if (!version || version->value() != 1U) {
-        return "AuthenticatedRequest version must be an unsigned integer and must be equal to 1.";
-    }
-    if (!diceCertChain) {
-        return "AuthenticatedRequest DiceCertChain must be an Array.";
-    }
-
-    // DICE chain is [ pubkey, + DiceChainEntry ].
+ErrMsgOr<hwtrust::DiceChain> getDiceChain(const std::vector<uint8_t>& encodedCsr, bool isFactory,
+                                          bool allowAnyMode, std::string_view instanceName) {
     auto diceChainKind = getDiceChainKind();
     if (!diceChainKind) {
         return diceChainKind.message();
     }
 
-    auto encodedDiceChain = diceCertChain->encode();
-    auto chain = hwtrust::DiceChain::Verify(encodedDiceChain, *diceChainKind);
-    if (!chain.ok()) return chain.error().message();
-    return chain->IsProper();
+    auto csr = hwtrust::Csr::validate(encodedCsr, *diceChainKind, isFactory, allowAnyMode,
+                                      deviceSuffix(instanceName));
+    if (!csr.ok()) {
+        return csr.error().message();
+    }
+
+    auto diceChain = csr->getDiceChain();
+    if (!diceChain.ok()) {
+        return diceChain.error().message();
+    }
+
+    return std::move(*diceChain);
+}
+
+ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& encodedCsr,
+                                        const std::string& instanceName) {
+    auto diceChain =
+            getDiceChain(encodedCsr, /*isFactory=*/false, /*allowAnyMode=*/true, instanceName);
+    if (!diceChain) {
+        return diceChain.message();
+    }
+    return diceChain->IsProper();
+}
+
+std::string hexlify(const std::vector<uint8_t>& bytes) {
+    std::stringstream ss;
+    ss << std::hex << std::setfill('0');
+
+    for (const auto& byte : bytes) {
+        ss << std::setw(2) << static_cast<int>(byte);
+    }
+
+    return ss.str();
+}
+
+ErrMsgOr<bool> compareRootPublicKeysInDiceChains(const std::vector<uint8_t>& encodedCsr1,
+                                                 std::string_view instanceName1,
+                                                 const std::vector<uint8_t>& encodedCsr2,
+                                                 std::string_view instanceName2) {
+    auto diceChain1 =
+            getDiceChain(encodedCsr1, /*isFactory=*/false, /*allowAnyMode=*/true, instanceName1);
+    if (!diceChain1) {
+        return diceChain1.message();
+    }
+
+    auto proper1 = diceChain1->IsProper();
+    if (!proper1) {
+        return std::string(instanceName1) + " has a degenerate DICE chain:\n" +
+               hexlify(encodedCsr1);
+    }
+
+    auto diceChain2 =
+            getDiceChain(encodedCsr2, /*isFactory=*/false, /*allowAnyMode=*/true, instanceName2);
+    if (!diceChain2) {
+        return diceChain2.message();
+    }
+
+    auto proper2 = diceChain2->IsProper();
+    if (!proper2) {
+        return std::string(instanceName2) + " has a degenerate DICE chain:\n" +
+               hexlify(encodedCsr2);
+    }
+
+    auto result = diceChain1->compareRootPublicKey(*diceChain2);
+    if (!result.ok()) {
+        return result.error().message();
+    }
+
+    return *result;
+}
+
+ErrMsgOr<bool> verifyComponentNameInKeyMintDiceChain(const std::vector<uint8_t>& encodedCsr) {
+    auto diceChain = getDiceChain(encodedCsr, /*isFactory=*/false, /*allowAnyMode=*/true,
+                                  DEFAULT_INSTANCE_NAME);
+    if (!diceChain) {
+        return diceChain.message();
+    }
+
+    auto satisfied = diceChain->componentNameContains(kKeyMintComponentName);
+    if (!satisfied.ok()) {
+        return satisfied.error().message();
+    }
+
+    return *satisfied;
+}
+
+ErrMsgOr<bool> hasNonNormalModeInDiceChain(const std::vector<uint8_t>& encodedCsr,
+                                           std::string_view instanceName) {
+    auto diceChain =
+            getDiceChain(encodedCsr, /*isFactory=*/false, /*allowAnyMode=*/true, instanceName);
+    if (!diceChain) {
+        return diceChain.message();
+    }
+
+    auto hasNonNormalModeInDiceChain = diceChain->hasNonNormalMode();
+    if (!hasNonNormalModeInDiceChain.ok()) {
+        return hasNonNormalModeInDiceChain.error().message();
+    }
+
+    return *hasNonNormalModeInDiceChain;
 }
 
 }  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/keymint/support/remote_prov_utils_test.cpp b/security/keymint/support/remote_prov_utils_test.cpp
index 89469f1..e3c1e58 100644
--- a/security/keymint/support/remote_prov_utils_test.cpp
+++ b/security/keymint/support/remote_prov_utils_test.cpp
@@ -41,6 +41,646 @@
 using ::testing::ElementsAreArray;
 using byte_view = std::span<const uint8_t>;
 
+using ::cppbor::Array;
+using ::cppbor::parse;
+using ::ndk::SharedRefBase;
+using ::testing::NotNull;
+
+inline const std::vector<uint8_t> kDegenerateBcc{
+        0x82, 0xa5, 0x01, 0x01, 0x03, 0x27, 0x04, 0x81, 0x02, 0x20, 0x06, 0x21, 0x58, 0x20, 0xf5,
+        0x5a, 0xfb, 0x28, 0x06, 0x48, 0x68, 0xea, 0x49, 0x3e, 0x47, 0x80, 0x1d, 0xfe, 0x1f, 0xfc,
+        0xa8, 0x84, 0xb3, 0x4d, 0xdb, 0x99, 0xc7, 0xbf, 0x23, 0x53, 0xe5, 0x71, 0x92, 0x41, 0x9b,
+        0x46, 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x59, 0x01, 0x75, 0xa9, 0x01, 0x78, 0x28, 0x31,
+        0x64, 0x34, 0x35, 0x65, 0x33, 0x35, 0x63, 0x34, 0x35, 0x37, 0x33, 0x31, 0x61, 0x32, 0x62,
+        0x34, 0x35, 0x36, 0x37, 0x63, 0x33, 0x63, 0x65, 0x35, 0x31, 0x36, 0x66, 0x35, 0x63, 0x31,
+        0x66, 0x34, 0x33, 0x61, 0x62, 0x64, 0x36, 0x30, 0x62, 0x02, 0x78, 0x28, 0x31, 0x64, 0x34,
+        0x35, 0x65, 0x33, 0x35, 0x63, 0x34, 0x35, 0x37, 0x33, 0x31, 0x61, 0x32, 0x62, 0x34, 0x35,
+        0x36, 0x37, 0x63, 0x33, 0x63, 0x65, 0x35, 0x31, 0x36, 0x66, 0x35, 0x63, 0x31, 0x66, 0x34,
+        0x33, 0x61, 0x62, 0x64, 0x36, 0x30, 0x62, 0x3a, 0x00, 0x47, 0x44, 0x50, 0x58, 0x40, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x41, 0xa0, 0x3a, 0x00, 0x47, 0x44, 0x52,
+        0x58, 0x40, 0x71, 0xd7, 0x47, 0x9e, 0x61, 0xb5, 0x30, 0xa3, 0xda, 0xe6, 0xac, 0xb2, 0x91,
+        0xa4, 0xf9, 0xcf, 0x7f, 0xba, 0x6b, 0x5f, 0xf9, 0xa3, 0x7f, 0xba, 0xab, 0xac, 0x69, 0xdd,
+        0x0b, 0x04, 0xd6, 0x34, 0xd2, 0x3f, 0x8f, 0x84, 0x96, 0xd7, 0x58, 0x51, 0x1d, 0x68, 0x25,
+        0xea, 0xbe, 0x11, 0x11, 0x1e, 0xd8, 0xdf, 0x4b, 0x62, 0x78, 0x5c, 0xa8, 0xfa, 0xb7, 0x66,
+        0x4e, 0x8d, 0xac, 0x3b, 0x00, 0x4c, 0x3a, 0x00, 0x47, 0x44, 0x54, 0x58, 0x40, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x3a, 0x00, 0x47, 0x44, 0x56, 0x41, 0x00, 0x3a, 0x00, 0x47, 0x44, 0x57, 0x58,
+        0x2d, 0xa5, 0x01, 0x01, 0x03, 0x27, 0x04, 0x81, 0x02, 0x20, 0x06, 0x21, 0x58, 0x20, 0xf5,
+        0x5a, 0xfb, 0x28, 0x06, 0x48, 0x68, 0xea, 0x49, 0x3e, 0x47, 0x80, 0x1d, 0xfe, 0x1f, 0xfc,
+        0xa8, 0x84, 0xb3, 0x4d, 0xdb, 0x99, 0xc7, 0xbf, 0x23, 0x53, 0xe5, 0x71, 0x92, 0x41, 0x9b,
+        0x46, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40, 0x31, 0x5c, 0x43, 0x87, 0xf9,
+        0xbb, 0xb9, 0x45, 0x09, 0xa8, 0xe8, 0x08, 0x70, 0xc4, 0xd9, 0xdc, 0x4e, 0x5a, 0x19, 0x10,
+        0x4f, 0xa3, 0x21, 0x20, 0x34, 0x05, 0x5b, 0x2e, 0x78, 0x91, 0xd1, 0xe2, 0x39, 0x43, 0x8b,
+        0x50, 0x12, 0x82, 0x37, 0xfe, 0xa4, 0x07, 0xc3, 0xd5, 0xc3, 0x78, 0xcc, 0xf9, 0xef, 0xe1,
+        0x95, 0x38, 0x9f, 0xb0, 0x79, 0x16, 0x4c, 0x4a, 0x23, 0xc4, 0xdc, 0x35, 0x4e, 0x0f};
+
+inline const std::vector<uint8_t> kKeysToSignForCsrWithDegenerateDiceChain{
+        0x82, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x1d, 0x94, 0xf2, 0x27,
+        0xc3, 0x70, 0x01, 0xde, 0x3c, 0xaf, 0x6f, 0xfd, 0x78, 0x08, 0x37, 0x39, 0x21, 0xdd, 0x46,
+        0x6f, 0x08, 0x4f, 0x77, 0xf7, 0x80, 0x34, 0x30, 0x74, 0x78, 0x69, 0xeb, 0xb1, 0x22, 0x58,
+        0x20, 0x6b, 0x71, 0xd7, 0x7f, 0x0e, 0x51, 0xb2, 0xc9, 0x3d, 0x1a, 0xa0, 0xe8, 0x7a, 0x0d,
+        0x57, 0xfc, 0x91, 0xd0, 0x68, 0xf9, 0x33, 0x5f, 0x80, 0x29, 0x00, 0x80, 0x98, 0x78, 0x63,
+        0x5b, 0x30, 0x24, 0x23, 0x58, 0x20, 0x09, 0x83, 0xa6, 0x5a, 0xbb, 0x3a, 0xf8, 0x90, 0x88,
+        0x87, 0x16, 0x37, 0xb4, 0xe7, 0x11, 0x9b, 0xcc, 0xbb, 0x15, 0x82, 0xa9, 0x97, 0xa5, 0xad,
+        0xa9, 0x85, 0x39, 0x30, 0x55, 0x46, 0x99, 0xc6, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01,
+        0x21, 0x58, 0x20, 0xa8, 0xaa, 0x4b, 0x63, 0x86, 0xf6, 0x5c, 0xe4, 0x28, 0xda, 0x26, 0x3f,
+        0x9a, 0x42, 0x6e, 0xb9, 0x2b, 0x4d, 0x5a, 0x49, 0x4c, 0x5f, 0x1a, 0xa2, 0x5f, 0xd4, 0x8f,
+        0x84, 0xd7, 0x25, 0xe4, 0x6c, 0x22, 0x58, 0x20, 0x6b, 0xef, 0xde, 0xd6, 0x04, 0x58, 0x12,
+        0xdb, 0xf8, 0x90, 0x2c, 0x9c, 0xe0, 0x5e, 0x43, 0xbc, 0xcf, 0x22, 0x01, 0x4d, 0x5c, 0x0c,
+        0x86, 0x7b, 0x66, 0xd2, 0xa1, 0xfc, 0x69, 0x8a, 0x91, 0xfc, 0x23, 0x58, 0x20, 0x31, 0xaf,
+        0x30, 0x85, 0x1f, 0x2a, 0x82, 0xe1, 0x9c, 0xda, 0xe5, 0x68, 0xed, 0x79, 0xc1, 0x35, 0x1a,
+        0x02, 0xb4, 0x8a, 0xd2, 0x4c, 0xc4, 0x70, 0x6b, 0x88, 0x98, 0x23, 0x9e, 0xb3, 0x52, 0xb1};
+
+inline const std::vector<uint8_t> kCsrWithDegenerateDiceChain{
+        0x84, 0x01, 0xa0, 0x82, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xf2,
+        0xc6, 0x50, 0xd2, 0x42, 0x59, 0xe0, 0x4e, 0x7b, 0xc0, 0x75, 0x41, 0xa2, 0xe9, 0xd0, 0xe8,
+        0x18, 0xd7, 0xd7, 0x63, 0x7e, 0x41, 0x04, 0x7e, 0x52, 0x1a, 0xb1, 0xb7, 0xdc, 0x13, 0xb3,
+        0x0f, 0x22, 0x58, 0x20, 0x1a, 0xf3, 0x8b, 0x0f, 0x7a, 0xc6, 0xf2, 0xb8, 0x31, 0x0b, 0x40,
+        0x9b, 0x7e, 0xb6, 0xd6, 0xec, 0x9c, 0x21, 0xad, 0xde, 0xd1, 0x6c, 0x52, 0xfc, 0x06, 0xf1,
+        0x39, 0x31, 0xa0, 0x22, 0x65, 0x86, 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x58, 0x74, 0xa5,
+        0x01, 0x66, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x02, 0x67, 0x73, 0x75, 0x62, 0x6a, 0x65,
+        0x63, 0x74, 0x3a, 0x00, 0x47, 0x44, 0x56, 0x41, 0x01, 0x3a, 0x00, 0x47, 0x44, 0x57, 0x58,
+        0x4d, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xf2, 0xc6, 0x50, 0xd2,
+        0x42, 0x59, 0xe0, 0x4e, 0x7b, 0xc0, 0x75, 0x41, 0xa2, 0xe9, 0xd0, 0xe8, 0x18, 0xd7, 0xd7,
+        0x63, 0x7e, 0x41, 0x04, 0x7e, 0x52, 0x1a, 0xb1, 0xb7, 0xdc, 0x13, 0xb3, 0x0f, 0x22, 0x58,
+        0x20, 0x1a, 0xf3, 0x8b, 0x0f, 0x7a, 0xc6, 0xf2, 0xb8, 0x31, 0x0b, 0x40, 0x9b, 0x7e, 0xb6,
+        0xd6, 0xec, 0x9c, 0x21, 0xad, 0xde, 0xd1, 0x6c, 0x52, 0xfc, 0x06, 0xf1, 0x39, 0x31, 0xa0,
+        0x22, 0x65, 0x86, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40, 0x1e, 0xdf, 0xe0,
+        0x1c, 0xca, 0xbb, 0xb2, 0x13, 0xae, 0xe2, 0x49, 0x32, 0x3c, 0x6e, 0x9c, 0x6e, 0xf4, 0x23,
+        0x87, 0x41, 0x60, 0x04, 0x34, 0xe6, 0x32, 0xe2, 0xf1, 0x22, 0x55, 0xcc, 0x89, 0x4b, 0x4f,
+        0xdb, 0x05, 0x89, 0x8a, 0x3c, 0x2f, 0x8a, 0x52, 0x84, 0x43, 0xdc, 0x43, 0x62, 0x7e, 0x85,
+        0xb3, 0xea, 0x49, 0x3b, 0x0b, 0x4a, 0xf0, 0x64, 0xfe, 0x8f, 0x41, 0xb6, 0xd1, 0xcc, 0xe3,
+        0xf6, 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x59, 0x02, 0x0e, 0x82, 0x58, 0x20, 0x01, 0x02,
+        0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+        0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+        0x59, 0x01, 0xe8, 0x84, 0x03, 0x67, 0x6b, 0x65, 0x79, 0x6d, 0x69, 0x6e, 0x74, 0xae, 0x65,
+        0x62, 0x72, 0x61, 0x6e, 0x64, 0x66, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x65, 0x66, 0x75,
+        0x73, 0x65, 0x64, 0x01, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x6f, 0x64, 0x65,
+        0x6c, 0x66, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x66, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
+        0x67, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x65, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x68,
+        0x76, 0x62, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x65, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x6a,
+        0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x62, 0x31, 0x32, 0x6c, 0x6d,
+        0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x66, 0x47, 0x6f, 0x6f,
+        0x67, 0x6c, 0x65, 0x6d, 0x76, 0x62, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x64, 0x69, 0x67, 0x65,
+        0x73, 0x74, 0x4f, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
+        0xdd, 0xee, 0xff, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x6c, 0x65,
+        0x76, 0x65, 0x6c, 0x63, 0x74, 0x65, 0x65, 0x70, 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x70, 0x61,
+        0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x62, 0x70,
+        0x62, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74,
+        0x65, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x72, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+        0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34,
+        0x8c, 0x61, 0x72, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68,
+        0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x63, 0x82, 0xa6, 0x01, 0x02,
+        0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x1d, 0x94, 0xf2, 0x27, 0xc3, 0x70, 0x01, 0xde,
+        0x3c, 0xaf, 0x6f, 0xfd, 0x78, 0x08, 0x37, 0x39, 0x21, 0xdd, 0x46, 0x6f, 0x08, 0x4f, 0x77,
+        0xf7, 0x80, 0x34, 0x30, 0x74, 0x78, 0x69, 0xeb, 0xb1, 0x22, 0x58, 0x20, 0x6b, 0x71, 0xd7,
+        0x7f, 0x0e, 0x51, 0xb2, 0xc9, 0x3d, 0x1a, 0xa0, 0xe8, 0x7a, 0x0d, 0x57, 0xfc, 0x91, 0xd0,
+        0x68, 0xf9, 0x33, 0x5f, 0x80, 0x29, 0x00, 0x80, 0x98, 0x78, 0x63, 0x5b, 0x30, 0x24, 0x23,
+        0x58, 0x20, 0x09, 0x83, 0xa6, 0x5a, 0xbb, 0x3a, 0xf8, 0x90, 0x88, 0x87, 0x16, 0x37, 0xb4,
+        0xe7, 0x11, 0x9b, 0xcc, 0xbb, 0x15, 0x82, 0xa9, 0x97, 0xa5, 0xad, 0xa9, 0x85, 0x39, 0x30,
+        0x55, 0x46, 0x99, 0xc6, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xa8,
+        0xaa, 0x4b, 0x63, 0x86, 0xf6, 0x5c, 0xe4, 0x28, 0xda, 0x26, 0x3f, 0x9a, 0x42, 0x6e, 0xb9,
+        0x2b, 0x4d, 0x5a, 0x49, 0x4c, 0x5f, 0x1a, 0xa2, 0x5f, 0xd4, 0x8f, 0x84, 0xd7, 0x25, 0xe4,
+        0x6c, 0x22, 0x58, 0x20, 0x6b, 0xef, 0xde, 0xd6, 0x04, 0x58, 0x12, 0xdb, 0xf8, 0x90, 0x2c,
+        0x9c, 0xe0, 0x5e, 0x43, 0xbc, 0xcf, 0x22, 0x01, 0x4d, 0x5c, 0x0c, 0x86, 0x7b, 0x66, 0xd2,
+        0xa1, 0xfc, 0x69, 0x8a, 0x91, 0xfc, 0x23, 0x58, 0x20, 0x31, 0xaf, 0x30, 0x85, 0x1f, 0x2a,
+        0x82, 0xe1, 0x9c, 0xda, 0xe5, 0x68, 0xed, 0x79, 0xc1, 0x35, 0x1a, 0x02, 0xb4, 0x8a, 0xd2,
+        0x4c, 0xc4, 0x70, 0x6b, 0x88, 0x98, 0x23, 0x9e, 0xb3, 0x52, 0xb1, 0x58, 0x40, 0x8e, 0x7e,
+        0xdf, 0x77, 0x13, 0xdb, 0x51, 0xf6, 0xc1, 0x67, 0x52, 0x48, 0x48, 0x79, 0xe6, 0xbc, 0x89,
+        0xe2, 0xfe, 0x7c, 0x0d, 0x2c, 0x88, 0x3b, 0x23, 0x66, 0x93, 0x7b, 0x94, 0x59, 0xc4, 0x87,
+        0x16, 0xc4, 0x3a, 0x85, 0x60, 0xe3, 0x62, 0x45, 0x53, 0xa8, 0x1d, 0x4e, 0xa4, 0x2b, 0x61,
+        0x33, 0x17, 0x71, 0xb6, 0x40, 0x11, 0x7d, 0x23, 0x64, 0xe6, 0x49, 0xbe, 0xa6, 0x85, 0x32,
+        0x1a, 0x89};
+
+// The challenge that is in kKeysToSignForCsrWithUdsCerts and kCsrWithUdsCerts
+inline const std::vector<uint8_t> kChallenge{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+                                             0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+                                             0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+                                             0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20};
+
+inline const std::vector<uint8_t> kKeysToSignForCsrWithUdsCerts{
+        0x82, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xd5, 0x0b, 0x27, 0x39,
+        0xa3, 0xd5, 0xfd, 0xd9, 0x4f, 0x87, 0x4a, 0x97, 0x17, 0x60, 0x6c, 0x63, 0x55, 0x13, 0xa0,
+        0xf5, 0x1c, 0x2b, 0xe7, 0x0e, 0x8e, 0xdb, 0x76, 0x82, 0x69, 0x5a, 0x46, 0xec, 0x22, 0x58,
+        0x20, 0xa6, 0x08, 0xb3, 0x57, 0xaa, 0x5f, 0x72, 0x2b, 0xb1, 0xf0, 0x43, 0x52, 0xf4, 0xcb,
+        0x97, 0x39, 0xfd, 0x54, 0x79, 0xa3, 0xaf, 0x07, 0xb7, 0xbe, 0xbc, 0x93, 0xc1, 0xb6, 0x9b,
+        0x2f, 0x75, 0x1b, 0x23, 0x58, 0x21, 0x00, 0xb4, 0x59, 0xe3, 0x78, 0x6f, 0x3f, 0xbd, 0xdc,
+        0x38, 0x8a, 0xa5, 0x7d, 0xbe, 0xe0, 0xce, 0xf9, 0x2e, 0x9a, 0x5b, 0xfc, 0xbd, 0x4d, 0x27,
+        0x7b, 0xa7, 0xc8, 0xda, 0xaa, 0xe4, 0xcd, 0xf3, 0xd2, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20,
+        0x01, 0x21, 0x58, 0x20, 0x10, 0x6c, 0xe8, 0x71, 0xa8, 0x78, 0x9d, 0x29, 0xbe, 0xf8, 0x84,
+        0x39, 0xd4, 0xa2, 0xf5, 0x3e, 0x09, 0xf1, 0xd4, 0x81, 0x59, 0x24, 0x63, 0x07, 0xae, 0x25,
+        0xad, 0x24, 0x72, 0x0f, 0x8b, 0xd0, 0x22, 0x58, 0x20, 0xe8, 0xba, 0x76, 0x49, 0x7b, 0x97,
+        0x98, 0xcf, 0xbb, 0x90, 0xfa, 0x30, 0x3a, 0x2d, 0x88, 0xfe, 0x3f, 0xc6, 0x75, 0x05, 0x7b,
+        0x59, 0xdf, 0x14, 0xd8, 0xde, 0x4d, 0x51, 0x8b, 0x2f, 0x5a, 0xc7, 0x23, 0x58, 0x20, 0x76,
+        0x11, 0x2f, 0x31, 0xe5, 0xc2, 0xbb, 0xa7, 0x2c, 0x2b, 0x2f, 0x73, 0x16, 0x29, 0xf8, 0x67,
+        0x66, 0x44, 0x7f, 0x3f, 0x22, 0xa2, 0x40, 0x45, 0x12, 0xac, 0x97, 0x06, 0xc8, 0x66, 0x08,
+        0xc9, 0x0a};
+
+inline const std::vector<uint8_t> kCsrWithUdsCerts{
+        0x84, 0x01, 0xa1, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72,
+        0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0x59, 0x01, 0x6c, 0x30, 0x82, 0x01, 0x68, 0x30, 0x82,
+        0x01, 0x1a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x7b, 0x30, 0x05, 0x06, 0x03, 0x2b,
+        0x65, 0x70, 0x30, 0x2b, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c,
+        0x46, 0x61, 0x6b, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31, 0x12, 0x30,
+        0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x09, 0x46, 0x61, 0x6b, 0x65, 0x20, 0x52, 0x6f,
+        0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x34, 0x31, 0x31, 0x31, 0x34, 0x30, 0x39, 0x35,
+        0x32, 0x30, 0x37, 0x5a, 0x17, 0x0d, 0x34, 0x39, 0x31, 0x31, 0x30, 0x38, 0x30, 0x39, 0x35,
+        0x32, 0x30, 0x37, 0x5a, 0x30, 0x2b, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a,
+        0x13, 0x0c, 0x46, 0x61, 0x6b, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31,
+        0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x09, 0x46, 0x61, 0x6b, 0x65, 0x20,
+        0x52, 0x6f, 0x6f, 0x74, 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21,
+        0x00, 0x54, 0x40, 0x8c, 0x1b, 0x60, 0x39, 0x81, 0xe7, 0x38, 0x87, 0xb9, 0x75, 0x10, 0x30,
+        0x6a, 0x1b, 0x9b, 0x38, 0x61, 0xa0, 0x94, 0x49, 0xb0, 0xf3, 0xae, 0x39, 0x53, 0x2d, 0x61,
+        0x8d, 0x6e, 0x59, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
+        0x16, 0x04, 0x14, 0x6d, 0xd5, 0xea, 0x8c, 0xe0, 0x5a, 0x50, 0xd9, 0x36, 0xf3, 0x28, 0xc2,
+        0x54, 0x1d, 0xfa, 0x9d, 0x94, 0x19, 0x98, 0x76, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23,
+        0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x6d, 0xd5, 0xea, 0x8c, 0xe0, 0x5a, 0x50, 0xd9, 0x36,
+        0xf3, 0x28, 0xc2, 0x54, 0x1d, 0xfa, 0x9d, 0x94, 0x19, 0x98, 0x76, 0x30, 0x0f, 0x06, 0x03,
+        0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e,
+        0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30,
+        0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x41, 0x00, 0x1e, 0x27, 0x99, 0xd3, 0x05, 0xa7,
+        0xd2, 0xc6, 0xad, 0x1f, 0x2c, 0xbd, 0xef, 0x34, 0x18, 0xbd, 0x37, 0xb9, 0x96, 0x57, 0x63,
+        0x72, 0x7e, 0xf8, 0xe5, 0xa2, 0xb5, 0x9a, 0x20, 0x42, 0x1d, 0x9c, 0x8e, 0xdc, 0x97, 0xd4,
+        0x3b, 0x65, 0xe0, 0x52, 0xb4, 0x0d, 0x95, 0x59, 0x94, 0x94, 0x7a, 0x31, 0x9e, 0x45, 0x4b,
+        0x93, 0x3d, 0x5d, 0x88, 0x98, 0xb1, 0x52, 0xf5, 0x46, 0x1c, 0x2a, 0x0b, 0x05, 0x59, 0x01,
+        0x9f, 0x30, 0x82, 0x01, 0x9b, 0x30, 0x82, 0x01, 0x4d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
+        0x02, 0x01, 0xc8, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x30, 0x2b, 0x31, 0x15, 0x30,
+        0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x46, 0x61, 0x6b, 0x65, 0x20, 0x43, 0x6f,
+        0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+        0x09, 0x46, 0x61, 0x6b, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x32,
+        0x34, 0x31, 0x31, 0x31, 0x34, 0x30, 0x39, 0x35, 0x32, 0x30, 0x37, 0x5a, 0x17, 0x0d, 0x34,
+        0x39, 0x31, 0x31, 0x30, 0x38, 0x30, 0x39, 0x35, 0x32, 0x30, 0x37, 0x5a, 0x30, 0x2e, 0x31,
+        0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x46, 0x61, 0x6b, 0x65, 0x20,
+        0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04,
+        0x03, 0x13, 0x0c, 0x46, 0x61, 0x6b, 0x65, 0x20, 0x43, 0x68, 0x69, 0x70, 0x73, 0x65, 0x74,
+        0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08,
+        0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xc9, 0x35, 0xf7,
+        0x7e, 0x71, 0xc9, 0xa4, 0xd2, 0x13, 0x58, 0x5a, 0xc1, 0x0c, 0x17, 0xa8, 0x2c, 0x28, 0x99,
+        0x32, 0x8e, 0x01, 0x45, 0xb8, 0xf1, 0xf4, 0xf8, 0x37, 0x25, 0x4a, 0x25, 0x1f, 0xbf, 0x8f,
+        0xd8, 0xdf, 0x53, 0xdd, 0x95, 0x7a, 0x90, 0xff, 0xe3, 0x40, 0xbf, 0xda, 0x19, 0x0c, 0x14,
+        0x41, 0x1c, 0x76, 0x73, 0x4e, 0x86, 0x94, 0x7d, 0x2c, 0x21, 0x5f, 0x5e, 0x05, 0x26, 0x15,
+        0x4f, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
+        0x14, 0x12, 0x84, 0xe1, 0x31, 0xef, 0xa8, 0xfd, 0xcc, 0xbb, 0x35, 0x22, 0xb9, 0x99, 0xd1,
+        0xca, 0x64, 0x19, 0x09, 0x54, 0x4c, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
+        0x30, 0x16, 0x80, 0x14, 0x6d, 0xd5, 0xea, 0x8c, 0xe0, 0x5a, 0x50, 0xd9, 0x36, 0xf3, 0x28,
+        0xc2, 0x54, 0x1d, 0xfa, 0x9d, 0x94, 0x19, 0x98, 0x76, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
+        0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03,
+        0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x05, 0x06,
+        0x03, 0x2b, 0x65, 0x70, 0x03, 0x41, 0x00, 0xc7, 0x93, 0x86, 0x58, 0xb2, 0x31, 0x30, 0x4f,
+        0x1a, 0x53, 0x06, 0x87, 0x0e, 0xdf, 0xc4, 0xd8, 0x03, 0xf4, 0xaf, 0xa3, 0x2d, 0xfb, 0x7d,
+        0xab, 0x08, 0x70, 0x47, 0x38, 0x10, 0xc5, 0xa8, 0x5e, 0x67, 0x64, 0xc7, 0xdc, 0x28, 0xe8,
+        0x63, 0x3c, 0xa7, 0xb8, 0xf9, 0xbe, 0x3e, 0x75, 0xa7, 0x1c, 0xac, 0xc4, 0x81, 0x82, 0x4a,
+        0x21, 0xf0, 0x89, 0x8e, 0x99, 0xf4, 0x52, 0x23, 0x30, 0x6d, 0x04, 0x82, 0xa5, 0x01, 0x02,
+        0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xc9, 0x35, 0xf7, 0x7e, 0x71, 0xc9, 0xa4, 0xd2,
+        0x13, 0x58, 0x5a, 0xc1, 0x0c, 0x17, 0xa8, 0x2c, 0x28, 0x99, 0x32, 0x8e, 0x01, 0x45, 0xb8,
+        0xf1, 0xf4, 0xf8, 0x37, 0x25, 0x4a, 0x25, 0x1f, 0xbf, 0x22, 0x58, 0x20, 0x8f, 0xd8, 0xdf,
+        0x53, 0xdd, 0x95, 0x7a, 0x90, 0xff, 0xe3, 0x40, 0xbf, 0xda, 0x19, 0x0c, 0x14, 0x41, 0x1c,
+        0x76, 0x73, 0x4e, 0x86, 0x94, 0x7d, 0x2c, 0x21, 0x5f, 0x5e, 0x05, 0x26, 0x15, 0x4f, 0x84,
+        0x43, 0xa1, 0x01, 0x26, 0xa0, 0x59, 0x01, 0x04, 0xa9, 0x01, 0x66, 0x69, 0x73, 0x73, 0x75,
+        0x65, 0x72, 0x02, 0x67, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x00, 0x47, 0x44,
+        0x50, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47, 0x44, 0x52, 0x58, 0x20, 0xb8, 0x96, 0x54,
+        0xe2, 0x2c, 0xa4, 0xd2, 0x4a, 0x9c, 0x0e, 0x45, 0x11, 0xc8, 0xf2, 0x63, 0xf0, 0x66, 0x0d,
+        0x2e, 0x20, 0x48, 0x96, 0x90, 0x14, 0xf4, 0x54, 0x63, 0xc4, 0xf4, 0x39, 0x30, 0x38, 0x3a,
+        0x00, 0x47, 0x44, 0x53, 0x55, 0xa1, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x6e, 0x63, 0x6f, 0x6d,
+        0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x00, 0x47, 0x44,
+        0x54, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47, 0x44, 0x56, 0x41, 0x01, 0x3a, 0x00, 0x47,
+        0x44, 0x57, 0x58, 0x4d, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xb8,
+        0x42, 0x01, 0xd7, 0xf0, 0xb7, 0x57, 0x98, 0xe3, 0x05, 0xf5, 0xcf, 0xef, 0x7b, 0x38, 0x39,
+        0x6d, 0x55, 0x68, 0x72, 0xa6, 0x46, 0xd3, 0x16, 0x89, 0x1a, 0x3a, 0x9b, 0xc8, 0xce, 0xc0,
+        0x1c, 0x22, 0x58, 0x20, 0xd1, 0xd5, 0x0e, 0xb8, 0xd0, 0x99, 0x09, 0x41, 0x63, 0x93, 0x33,
+        0x20, 0xef, 0x84, 0xbb, 0xf5, 0xc9, 0x27, 0x4b, 0x52, 0x33, 0xa9, 0x07, 0xcc, 0x5d, 0x22,
+        0xab, 0xf6, 0x8f, 0x2d, 0x15, 0x41, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40,
+        0xd0, 0x6d, 0xb0, 0xd2, 0x49, 0xc8, 0xd3, 0x81, 0xdd, 0x10, 0x4b, 0xd9, 0x49, 0x45, 0x93,
+        0x10, 0xd5, 0x1b, 0xc7, 0x59, 0x66, 0x6f, 0x6c, 0x06, 0xb5, 0x72, 0x98, 0x51, 0x2d, 0xed,
+        0xa0, 0xd9, 0xbb, 0x4a, 0xe6, 0x9b, 0x67, 0x31, 0xd9, 0x27, 0xd0, 0x9c, 0xf8, 0x3d, 0xfc,
+        0x61, 0x8d, 0x53, 0x13, 0x53, 0x68, 0xb4, 0xb5, 0x41, 0x4c, 0xea, 0x6a, 0x28, 0xbb, 0xcb,
+        0x63, 0x4d, 0xd0, 0x20, 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x59, 0x02, 0x0f, 0x82, 0x58,
+        0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+        0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+        0x1e, 0x1f, 0x20, 0x59, 0x01, 0xe9, 0x84, 0x03, 0x67, 0x6b, 0x65, 0x79, 0x6d, 0x69, 0x6e,
+        0x74, 0xae, 0x65, 0x62, 0x72, 0x61, 0x6e, 0x64, 0x66, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+        0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x01, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x65, 0x6d,
+        0x6f, 0x64, 0x65, 0x6c, 0x66, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x66, 0x64, 0x65, 0x76,
+        0x69, 0x63, 0x65, 0x67, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x65, 0x70, 0x69, 0x78,
+        0x65, 0x6c, 0x68, 0x76, 0x62, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x65, 0x67, 0x72, 0x65,
+        0x65, 0x6e, 0x6a, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x62, 0x31,
+        0x32, 0x6c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x66,
+        0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x6d, 0x76, 0x62, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x64,
+        0x69, 0x67, 0x65, 0x73, 0x74, 0x4f, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+        0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
+        0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x63, 0x74, 0x65, 0x65, 0x70, 0x62, 0x6f, 0x6f, 0x74,
+        0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34,
+        0x8c, 0x62, 0x70, 0x62, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x73,
+        0x74, 0x61, 0x74, 0x65, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x72, 0x73, 0x79, 0x73,
+        0x74, 0x65, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c,
+        0x1a, 0x01, 0x34, 0x8c, 0x61, 0x72, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x70, 0x61,
+        0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x63, 0x82,
+        0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xd5, 0x0b, 0x27, 0x39, 0xa3,
+        0xd5, 0xfd, 0xd9, 0x4f, 0x87, 0x4a, 0x97, 0x17, 0x60, 0x6c, 0x63, 0x55, 0x13, 0xa0, 0xf5,
+        0x1c, 0x2b, 0xe7, 0x0e, 0x8e, 0xdb, 0x76, 0x82, 0x69, 0x5a, 0x46, 0xec, 0x22, 0x58, 0x20,
+        0xa6, 0x08, 0xb3, 0x57, 0xaa, 0x5f, 0x72, 0x2b, 0xb1, 0xf0, 0x43, 0x52, 0xf4, 0xcb, 0x97,
+        0x39, 0xfd, 0x54, 0x79, 0xa3, 0xaf, 0x07, 0xb7, 0xbe, 0xbc, 0x93, 0xc1, 0xb6, 0x9b, 0x2f,
+        0x75, 0x1b, 0x23, 0x58, 0x21, 0x00, 0xb4, 0x59, 0xe3, 0x78, 0x6f, 0x3f, 0xbd, 0xdc, 0x38,
+        0x8a, 0xa5, 0x7d, 0xbe, 0xe0, 0xce, 0xf9, 0x2e, 0x9a, 0x5b, 0xfc, 0xbd, 0x4d, 0x27, 0x7b,
+        0xa7, 0xc8, 0xda, 0xaa, 0xe4, 0xcd, 0xf3, 0xd2, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01,
+        0x21, 0x58, 0x20, 0x10, 0x6c, 0xe8, 0x71, 0xa8, 0x78, 0x9d, 0x29, 0xbe, 0xf8, 0x84, 0x39,
+        0xd4, 0xa2, 0xf5, 0x3e, 0x09, 0xf1, 0xd4, 0x81, 0x59, 0x24, 0x63, 0x07, 0xae, 0x25, 0xad,
+        0x24, 0x72, 0x0f, 0x8b, 0xd0, 0x22, 0x58, 0x20, 0xe8, 0xba, 0x76, 0x49, 0x7b, 0x97, 0x98,
+        0xcf, 0xbb, 0x90, 0xfa, 0x30, 0x3a, 0x2d, 0x88, 0xfe, 0x3f, 0xc6, 0x75, 0x05, 0x7b, 0x59,
+        0xdf, 0x14, 0xd8, 0xde, 0x4d, 0x51, 0x8b, 0x2f, 0x5a, 0xc7, 0x23, 0x58, 0x20, 0x76, 0x11,
+        0x2f, 0x31, 0xe5, 0xc2, 0xbb, 0xa7, 0x2c, 0x2b, 0x2f, 0x73, 0x16, 0x29, 0xf8, 0x67, 0x66,
+        0x44, 0x7f, 0x3f, 0x22, 0xa2, 0x40, 0x45, 0x12, 0xac, 0x97, 0x06, 0xc8, 0x66, 0x08, 0xc9,
+        0x58, 0x40, 0x11, 0x65, 0x46, 0xfa, 0xbd, 0xe3, 0xd3, 0x1b, 0x0d, 0x78, 0x23, 0x2e, 0x5d,
+        0x48, 0x3c, 0xab, 0xd3, 0x74, 0xf8, 0x41, 0x88, 0x9b, 0x48, 0xf3, 0x93, 0x06, 0x40, 0x1b,
+        0x5f, 0x60, 0x7b, 0xbe, 0xd8, 0xa6, 0x65, 0xff, 0x6a, 0x89, 0x24, 0x12, 0x1b, 0xac, 0xa3,
+        0xd5, 0x37, 0x85, 0x6e, 0x53, 0x8d, 0xa5, 0x07, 0xe7, 0xe7, 0x44, 0x2c, 0xba, 0xa0, 0xbe,
+        0x1a, 0x43, 0xde, 0x28, 0x59, 0x65};
+
+inline const std::vector<uint8_t> kKeysToSignForCsrWithoutUdsCerts = {
+        0x82, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x11, 0x29, 0x11, 0x96,
+        0x98, 0x26, 0xb2, 0x3a, 0xf2, 0xf9, 0x95, 0xb7, 0x46, 0xb9, 0x38, 0x6e, 0x5e, 0x3d, 0x5e,
+        0xb2, 0x19, 0x90, 0xc7, 0xd3, 0xbd, 0x49, 0x47, 0x55, 0xcb, 0xef, 0xeb, 0x89, 0x22, 0x58,
+        0x20, 0x42, 0x87, 0xea, 0x75, 0x27, 0x42, 0x34, 0xeb, 0xe8, 0xb5, 0x50, 0xdf, 0xb0, 0xbf,
+        0xef, 0x6b, 0x62, 0x90, 0x5c, 0xd1, 0xe8, 0x2b, 0x4d, 0x02, 0x58, 0xe6, 0xca, 0xda, 0xe6,
+        0x33, 0x97, 0xff, 0x23, 0x58, 0x21, 0x00, 0x9b, 0x34, 0xdb, 0x1e, 0xe6, 0x53, 0x72, 0xaf,
+        0x67, 0xb5, 0x5e, 0x9a, 0xee, 0x07, 0x31, 0x77, 0xa3, 0x8b, 0x6a, 0xe9, 0x58, 0x97, 0x04,
+        0xe2, 0xa2, 0x48, 0x0f, 0xdf, 0x26, 0x4d, 0xe5, 0xbb, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20,
+        0x01, 0x21, 0x58, 0x20, 0xf9, 0xd7, 0x37, 0x75, 0x6b, 0x55, 0xc7, 0x64, 0xf9, 0xe2, 0x59,
+        0x8f, 0x11, 0x48, 0xa1, 0xac, 0x95, 0xb1, 0xe3, 0x60, 0xe5, 0xa8, 0xa4, 0x2f, 0xb5, 0xcb,
+        0x90, 0x1e, 0x9e, 0xcb, 0x4c, 0xab, 0x22, 0x58, 0x20, 0x20, 0xad, 0x7b, 0xeb, 0xba, 0x5d,
+        0x3c, 0xd5, 0xa3, 0x6d, 0x86, 0x6e, 0x3f, 0x38, 0xb8, 0x44, 0x32, 0x4b, 0xe7, 0x97, 0xea,
+        0xf8, 0x3d, 0xc2, 0xc0, 0x7c, 0x1b, 0x49, 0xe4, 0x22, 0x23, 0xc7, 0x23, 0x58, 0x20, 0x5f,
+        0x1f, 0x80, 0xe2, 0xcf, 0x59, 0x1d, 0x7e, 0x98, 0x51, 0x78, 0xbe, 0xf8, 0x88, 0x0b, 0x64,
+        0x1b, 0xc8, 0xf2, 0x7b, 0x12, 0x22, 0x53, 0xd9, 0xd5, 0x8d, 0x32, 0xe7, 0x7f, 0x0e, 0x97,
+        0x09};
+
+inline const std::vector<uint8_t> kCsrWithoutUdsCerts{
+        0x84, 0x01, 0xa0, 0x82, 0xa4, 0x01, 0x01, 0x03, 0x27, 0x20, 0x06, 0x21, 0x58, 0x20, 0xca,
+        0x73, 0xd6, 0x09, 0x91, 0xec, 0x92, 0x63, 0xee, 0x9f, 0x7c, 0x79, 0x3e, 0x80, 0xa9, 0xc9,
+        0x4e, 0xf7, 0x3b, 0x5b, 0x41, 0xa4, 0x56, 0xc1, 0x9e, 0xf3, 0x80, 0x16, 0x6d, 0xfe, 0x14,
+        0x98, 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x59, 0x01, 0x04, 0xa9, 0x01, 0x66, 0x69, 0x73,
+        0x73, 0x75, 0x65, 0x72, 0x02, 0x67, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x00,
+        0x47, 0x44, 0x50, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47, 0x44, 0x52, 0x58, 0x20, 0xb8,
+        0x96, 0x54, 0xe2, 0x2c, 0xa4, 0xd2, 0x4a, 0x9c, 0x0e, 0x45, 0x11, 0xc8, 0xf2, 0x63, 0xf0,
+        0x66, 0x0d, 0x2e, 0x20, 0x48, 0x96, 0x90, 0x14, 0xf4, 0x54, 0x63, 0xc4, 0xf4, 0x39, 0x30,
+        0x38, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x55, 0xa1, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x6e, 0x63,
+        0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x00,
+        0x47, 0x44, 0x54, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47, 0x44, 0x56, 0x41, 0x01, 0x3a,
+        0x00, 0x47, 0x44, 0x57, 0x58, 0x4d, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58,
+        0x20, 0x45, 0x71, 0x10, 0x9a, 0x1b, 0x9c, 0x9f, 0x3c, 0x6e, 0x29, 0xf9, 0x6d, 0xb9, 0x93,
+        0x4a, 0xf2, 0x88, 0xf1, 0x3a, 0xf7, 0x69, 0xf9, 0xf3, 0x54, 0x91, 0x3a, 0x12, 0x4f, 0xd0,
+        0xbb, 0xb7, 0x0d, 0x22, 0x58, 0x20, 0x56, 0x8b, 0xb0, 0x0e, 0xd3, 0x8d, 0x12, 0xf5, 0x17,
+        0xd2, 0x6b, 0x21, 0xdf, 0x4d, 0xb8, 0xaa, 0x17, 0x65, 0x02, 0x4e, 0x5c, 0x0a, 0x77, 0x93,
+        0x64, 0x1e, 0x8d, 0xbc, 0x6a, 0xa1, 0x26, 0xe7, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20,
+        0x58, 0x40, 0xb0, 0x7b, 0xdd, 0xa5, 0x8e, 0xcb, 0xce, 0xf9, 0x89, 0xfb, 0x21, 0x4b, 0x29,
+        0x34, 0xff, 0x6b, 0x0e, 0xc1, 0xff, 0x51, 0xba, 0x12, 0x12, 0xa0, 0x93, 0x2c, 0x09, 0xca,
+        0x3a, 0x02, 0x81, 0x2a, 0x5b, 0x6f, 0x8d, 0x58, 0x21, 0x94, 0x30, 0xde, 0x99, 0x8b, 0x36,
+        0x69, 0x45, 0xa1, 0x52, 0x5c, 0x7b, 0x36, 0x4f, 0xec, 0x4f, 0x40, 0x5f, 0x10, 0xdf, 0x26,
+        0x18, 0xea, 0x4b, 0x72, 0x9f, 0x05, 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x59, 0x02, 0x0f,
+        0x82, 0x58, 0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+        0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+        0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x59, 0x01, 0xe9, 0x84, 0x03, 0x67, 0x6b, 0x65, 0x79, 0x6d,
+        0x69, 0x6e, 0x74, 0xae, 0x65, 0x62, 0x72, 0x61, 0x6e, 0x64, 0x66, 0x47, 0x6f, 0x6f, 0x67,
+        0x6c, 0x65, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x01, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
+        0x65, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x66, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x66, 0x64,
+        0x65, 0x76, 0x69, 0x63, 0x65, 0x67, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x65, 0x70,
+        0x69, 0x78, 0x65, 0x6c, 0x68, 0x76, 0x62, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x65, 0x67,
+        0x72, 0x65, 0x65, 0x6e, 0x6a, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+        0x62, 0x31, 0x32, 0x6c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65,
+        0x72, 0x66, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x6d, 0x76, 0x62, 0x6d, 0x65, 0x74, 0x61,
+        0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x4f, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69,
+        0x74, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x63, 0x74, 0x65, 0x65, 0x70, 0x62, 0x6f,
+        0x6f, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a,
+        0x01, 0x34, 0x8c, 0x62, 0x70, 0x62, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72,
+        0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x72, 0x73,
+        0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76,
+        0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x61, 0x72, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f,
+        0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c,
+        0x63, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x11, 0x29, 0x11,
+        0x96, 0x98, 0x26, 0xb2, 0x3a, 0xf2, 0xf9, 0x95, 0xb7, 0x46, 0xb9, 0x38, 0x6e, 0x5e, 0x3d,
+        0x5e, 0xb2, 0x19, 0x90, 0xc7, 0xd3, 0xbd, 0x49, 0x47, 0x55, 0xcb, 0xef, 0xeb, 0x89, 0x22,
+        0x58, 0x20, 0x42, 0x87, 0xea, 0x75, 0x27, 0x42, 0x34, 0xeb, 0xe8, 0xb5, 0x50, 0xdf, 0xb0,
+        0xbf, 0xef, 0x6b, 0x62, 0x90, 0x5c, 0xd1, 0xe8, 0x2b, 0x4d, 0x02, 0x58, 0xe6, 0xca, 0xda,
+        0xe6, 0x33, 0x97, 0xff, 0x23, 0x58, 0x21, 0x00, 0x9b, 0x34, 0xdb, 0x1e, 0xe6, 0x53, 0x72,
+        0xaf, 0x67, 0xb5, 0x5e, 0x9a, 0xee, 0x07, 0x31, 0x77, 0xa3, 0x8b, 0x6a, 0xe9, 0x58, 0x97,
+        0x04, 0xe2, 0xa2, 0x48, 0x0f, 0xdf, 0x26, 0x4d, 0xe5, 0xbb, 0xa6, 0x01, 0x02, 0x03, 0x26,
+        0x20, 0x01, 0x21, 0x58, 0x20, 0xf9, 0xd7, 0x37, 0x75, 0x6b, 0x55, 0xc7, 0x64, 0xf9, 0xe2,
+        0x59, 0x8f, 0x11, 0x48, 0xa1, 0xac, 0x95, 0xb1, 0xe3, 0x60, 0xe5, 0xa8, 0xa4, 0x2f, 0xb5,
+        0xcb, 0x90, 0x1e, 0x9e, 0xcb, 0x4c, 0xab, 0x22, 0x58, 0x20, 0x20, 0xad, 0x7b, 0xeb, 0xba,
+        0x5d, 0x3c, 0xd5, 0xa3, 0x6d, 0x86, 0x6e, 0x3f, 0x38, 0xb8, 0x44, 0x32, 0x4b, 0xe7, 0x97,
+        0xea, 0xf8, 0x3d, 0xc2, 0xc0, 0x7c, 0x1b, 0x49, 0xe4, 0x22, 0x23, 0xc7, 0x23, 0x58, 0x20,
+        0x5f, 0x1f, 0x80, 0xe2, 0xcf, 0x59, 0x1d, 0x7e, 0x98, 0x51, 0x78, 0xbe, 0xf8, 0x88, 0x0b,
+        0x64, 0x1b, 0xc8, 0xf2, 0x7b, 0x12, 0x22, 0x53, 0xd9, 0xd5, 0x8d, 0x32, 0xe7, 0x7f, 0x0e,
+        0x97, 0x09, 0x58, 0x40, 0xe1, 0x9a, 0x3f, 0x36, 0x65, 0x7a, 0xfe, 0x1b, 0x99, 0xc9, 0x35,
+        0x8f, 0xb5, 0x5c, 0xfe, 0x12, 0x9c, 0x6f, 0x0e, 0x97, 0x12, 0xbd, 0x26, 0x32, 0x46, 0xd9,
+        0x08, 0x6b, 0x7c, 0xa1, 0xd3, 0x47, 0xd6, 0xba, 0xf0, 0x9c, 0xe0, 0x12, 0x37, 0x39, 0x75,
+        0x88, 0xb5, 0xbe, 0xd8, 0x37, 0x33, 0x9b, 0x26, 0xfc, 0x38, 0x14, 0x28, 0xea, 0x47, 0xcc,
+        0x1f, 0xf3, 0xfe, 0x44, 0x0c, 0x1e, 0x6f, 0x2b, 0xa1, 0x6b, 0x66, 0x69, 0x6e, 0x67, 0x65,
+        0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x78, 0x3b, 0x62, 0x72, 0x61, 0x6e, 0x64, 0x31, 0x2f,
+        0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x31, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
+        0x31, 0x3a, 0x31, 0x31, 0x2f, 0x69, 0x64, 0x2f, 0x32, 0x30, 0x32, 0x31, 0x30, 0x38, 0x30,
+        0x35, 0x2e, 0x34, 0x32, 0x3a, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61,
+        0x73, 0x65, 0x2d, 0x6b, 0x65, 0x79, 0x73};
+
+inline const std::vector<uint8_t> kCsrWithKeyMintInComponentName{
+        0x84, 0x01, 0xa0, 0x82, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x44,
+        0xfd, 0xdd, 0xf1, 0x8a, 0x78, 0xa0, 0xbe, 0x37, 0x49, 0x51, 0x85, 0xfb, 0x7a, 0x16, 0xca,
+        0xc1, 0x00, 0xb3, 0x78, 0x13, 0x4a, 0x90, 0x4c, 0x5a, 0xa1, 0x3b, 0xfc, 0xea, 0xb6, 0xf3,
+        0x16, 0x22, 0x58, 0x20, 0x12, 0x7f, 0xf5, 0xe2, 0x14, 0xbd, 0x5d, 0x51, 0xd3, 0x7f, 0x2f,
+        0x1f, 0x9c, 0xc2, 0x18, 0x31, 0x94, 0x13, 0x52, 0x31, 0x3d, 0x43, 0xc9, 0x39, 0xbc, 0xc9,
+        0x06, 0xb0, 0xb2, 0xa9, 0x0e, 0x59, 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x59, 0x01, 0x0e,
+        0xa9, 0x01, 0x66, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x02, 0x67, 0x73, 0x75, 0x62, 0x6a,
+        0x65, 0x63, 0x74, 0x3a, 0x00, 0x47, 0x44, 0x50, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47,
+        0x44, 0x52, 0x58, 0x20, 0x88, 0x44, 0x82, 0xb6, 0x6c, 0x9c, 0xcb, 0x2e, 0xe8, 0xdc, 0xb4,
+        0xe9, 0xd3, 0xf7, 0x87, 0x63, 0x03, 0xaa, 0x90, 0x9d, 0xd9, 0xcb, 0xc3, 0x81, 0x03, 0x5b,
+        0xa9, 0xa2, 0x75, 0xe8, 0xfa, 0x50, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x58, 0x1e, 0xa1, 0x3a,
+        0x00, 0x01, 0x11, 0x71, 0x77, 0x4d, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20,
+        0x6a, 0x75, 0x73, 0x74, 0x20, 0x6b, 0x65, 0x79, 0x6d, 0x69, 0x6e, 0x74, 0x3f, 0x3a, 0x00,
+        0x47, 0x44, 0x54, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47, 0x44, 0x56, 0x41, 0x01, 0x3a,
+        0x00, 0x47, 0x44, 0x57, 0x58, 0x4d, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58,
+        0x20, 0xe7, 0x0e, 0x4b, 0xcb, 0x8d, 0x4a, 0xd0, 0x36, 0x7f, 0xbf, 0x19, 0xdd, 0x9a, 0xd9,
+        0x43, 0x62, 0xab, 0x29, 0x13, 0x1e, 0x14, 0x98, 0x68, 0xee, 0x5d, 0xae, 0xfa, 0x2f, 0x49,
+        0x99, 0xfa, 0x0b, 0x22, 0x58, 0x20, 0xfb, 0x9f, 0xd3, 0xd8, 0x67, 0x86, 0x81, 0x5f, 0xb3,
+        0x84, 0x00, 0x32, 0xc4, 0xe8, 0x7e, 0x9b, 0xb2, 0x4c, 0x1d, 0xd7, 0x71, 0x0d, 0x8f, 0xe0,
+        0x26, 0xc6, 0x73, 0xb1, 0x8f, 0x2d, 0x02, 0xf8, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20,
+        0x58, 0x40, 0x8f, 0xb9, 0x41, 0x5f, 0xa7, 0x48, 0xe4, 0xe3, 0xfb, 0x80, 0xbf, 0x2e, 0x30,
+        0xb8, 0xc9, 0x2c, 0xe4, 0x74, 0x4f, 0x4c, 0xb1, 0x79, 0xfb, 0x42, 0x43, 0x1e, 0xb4, 0x6c,
+        0x6a, 0x37, 0xaf, 0x3a, 0x76, 0x15, 0x16, 0x1f, 0x25, 0x26, 0x27, 0x1b, 0x9c, 0x5c, 0xcf,
+        0x9a, 0xfd, 0xb0, 0x82, 0xad, 0xe4, 0xd1, 0xd9, 0x04, 0x80, 0x80, 0x1a, 0x21, 0x12, 0x3e,
+        0x81, 0xff, 0x0c, 0x23, 0x3d, 0x0a, 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x59, 0x02, 0x10,
+        0x82, 0x58, 0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+        0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+        0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x59, 0x01, 0xea, 0x84, 0x03, 0x67, 0x6b, 0x65, 0x79, 0x6d,
+        0x69, 0x6e, 0x74, 0xae, 0x65, 0x62, 0x72, 0x61, 0x6e, 0x64, 0x66, 0x47, 0x6f, 0x6f, 0x67,
+        0x6c, 0x65, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x01, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
+        0x65, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x66, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x66, 0x64,
+        0x65, 0x76, 0x69, 0x63, 0x65, 0x67, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x65, 0x70,
+        0x69, 0x78, 0x65, 0x6c, 0x68, 0x76, 0x62, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x65, 0x67,
+        0x72, 0x65, 0x65, 0x6e, 0x6a, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+        0x62, 0x31, 0x32, 0x6c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65,
+        0x72, 0x66, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x6d, 0x76, 0x62, 0x6d, 0x65, 0x74, 0x61,
+        0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x4f, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69,
+        0x74, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x63, 0x74, 0x65, 0x65, 0x70, 0x62, 0x6f,
+        0x6f, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a,
+        0x01, 0x34, 0x8c, 0x62, 0x70, 0x62, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72,
+        0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x72, 0x73,
+        0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76,
+        0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x61, 0x72, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f,
+        0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c,
+        0x63, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x40, 0x9a, 0x39,
+        0x4d, 0xe2, 0xc5, 0x48, 0x58, 0x6e, 0xaa, 0x17, 0x81, 0x8a, 0xba, 0xc4, 0xea, 0x20, 0x23,
+        0xc4, 0xf3, 0xdc, 0xfa, 0x78, 0x9f, 0x5b, 0x7d, 0x30, 0xd2, 0x3d, 0x6f, 0x42, 0xa8, 0x22,
+        0x58, 0x20, 0x3e, 0x85, 0x73, 0xe5, 0x86, 0x57, 0x45, 0x72, 0xcd, 0xf2, 0xe8, 0x62, 0x93,
+        0xf3, 0xea, 0xbf, 0x21, 0x57, 0xa9, 0x25, 0xe7, 0xa8, 0x2a, 0xa0, 0xd0, 0x0a, 0x1d, 0xa5,
+        0x81, 0x22, 0xd0, 0xe1, 0x23, 0x58, 0x21, 0x00, 0x95, 0x00, 0xea, 0x43, 0x32, 0x8d, 0x2e,
+        0x1c, 0x18, 0x6d, 0x73, 0x34, 0xa2, 0xe4, 0x53, 0x64, 0x20, 0x95, 0x25, 0x8d, 0x4b, 0x97,
+        0x71, 0x13, 0xdf, 0xa6, 0x0e, 0xdc, 0x5b, 0x66, 0x66, 0x0b, 0xa6, 0x01, 0x02, 0x03, 0x26,
+        0x20, 0x01, 0x21, 0x58, 0x20, 0xa4, 0x81, 0xd9, 0xa0, 0x37, 0x89, 0xb1, 0x5d, 0x22, 0xf1,
+        0x22, 0x7e, 0x19, 0x00, 0xf1, 0x87, 0xdf, 0x10, 0x88, 0x1f, 0x64, 0xc5, 0x46, 0x6d, 0x91,
+        0x9d, 0x6c, 0x86, 0x3b, 0x67, 0x07, 0x14, 0x22, 0x58, 0x20, 0x3c, 0x42, 0x1f, 0x47, 0x62,
+        0x2c, 0x4f, 0x08, 0x29, 0xe9, 0xc6, 0x0c, 0x7c, 0xe5, 0x11, 0xc6, 0x39, 0x69, 0xc9, 0x9d,
+        0xdf, 0x69, 0x18, 0x8e, 0xdb, 0x99, 0x87, 0x52, 0x2f, 0x6b, 0xb4, 0x6a, 0x23, 0x58, 0x21,
+        0x00, 0x83, 0xa2, 0x6f, 0x5b, 0x3a, 0x71, 0x7c, 0x66, 0x3c, 0x96, 0x3f, 0x4e, 0x42, 0x6f,
+        0x98, 0x45, 0x1f, 0x59, 0x50, 0x03, 0x48, 0x9b, 0x57, 0xf5, 0x0e, 0x0f, 0x96, 0x30, 0xa4,
+        0xd6, 0xc3, 0x45, 0x58, 0x40, 0x8b, 0xdf, 0xc8, 0xc7, 0x6d, 0xa4, 0x02, 0xec, 0x3c, 0x5d,
+        0x90, 0x73, 0x0f, 0x8c, 0x10, 0x0f, 0x99, 0xd2, 0x85, 0x6e, 0x03, 0x45, 0x55, 0x28, 0xf7,
+        0x64, 0x0b, 0xbd, 0x7c, 0x3a, 0x69, 0xf1, 0x80, 0x1a, 0xf3, 0x93, 0x7e, 0x82, 0xfc, 0xa5,
+        0x3b, 0x69, 0x98, 0xf1, 0xde, 0x06, 0xb6, 0x72, 0x78, 0x0b, 0xdb, 0xbb, 0x97, 0x20, 0x04,
+        0x98, 0xb0, 0xd4, 0x07, 0x83, 0x65, 0xfb, 0xf8, 0x9c};
+
+inline std::vector<uint8_t> kCsrWithDebugMode{
+        0x84, 0x01, 0xa0, 0x82, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x03,
+        0x09, 0xad, 0x0d, 0x07, 0xec, 0x59, 0xfc, 0x14, 0x31, 0x21, 0x1f, 0xbc, 0x8e, 0x44, 0xe7,
+        0x0f, 0xa9, 0xb7, 0x5a, 0x57, 0x38, 0x5f, 0x76, 0x8a, 0xa3, 0x38, 0x2c, 0xf0, 0x1b, 0x37,
+        0x15, 0x22, 0x58, 0x20, 0x82, 0xae, 0x09, 0x76, 0x9c, 0x1d, 0x18, 0x39, 0x5d, 0x09, 0xf8,
+        0x19, 0x86, 0x70, 0x60, 0x12, 0x1e, 0x06, 0xb3, 0x68, 0x4a, 0x27, 0x2c, 0x79, 0xd3, 0x83,
+        0xb8, 0x54, 0x5b, 0x9f, 0xc0, 0x9f, 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x59, 0x01, 0x04,
+        0xa9, 0x01, 0x66, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x02, 0x67, 0x73, 0x75, 0x62, 0x6a,
+        0x65, 0x63, 0x74, 0x3a, 0x00, 0x47, 0x44, 0x50, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47,
+        0x44, 0x52, 0x58, 0x20, 0xb8, 0x96, 0x54, 0xe2, 0x2c, 0xa4, 0xd2, 0x4a, 0x9c, 0x0e, 0x45,
+        0x11, 0xc8, 0xf2, 0x63, 0xf0, 0x66, 0x0d, 0x2e, 0x20, 0x48, 0x96, 0x90, 0x14, 0xf4, 0x54,
+        0x63, 0xc4, 0xf4, 0x39, 0x30, 0x38, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x55, 0xa1, 0x3a, 0x00,
+        0x01, 0x11, 0x71, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x6e,
+        0x61, 0x6d, 0x65, 0x3a, 0x00, 0x47, 0x44, 0x54, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47,
+        0x44, 0x56, 0x41, 0x02, 0x3a, 0x00, 0x47, 0x44, 0x57, 0x58, 0x4d, 0xa5, 0x01, 0x02, 0x03,
+        0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x5f, 0xcf, 0x63, 0xcc, 0x24, 0x16, 0x66, 0x11, 0x6c,
+        0xaf, 0xed, 0xf4, 0x02, 0x8f, 0xc9, 0x14, 0xc7, 0x32, 0xa5, 0xdb, 0x41, 0x53, 0x54, 0x34,
+        0xcf, 0xcd, 0x6b, 0x4c, 0xb2, 0x22, 0x89, 0x96, 0x22, 0x58, 0x20, 0x4c, 0xed, 0xe3, 0x92,
+        0x94, 0x8f, 0x04, 0xd6, 0x04, 0x3a, 0x6c, 0x15, 0x5f, 0xbb, 0x52, 0x4a, 0x7d, 0x94, 0xcf,
+        0x31, 0x49, 0x31, 0x28, 0x66, 0x38, 0xe2, 0x40, 0x3e, 0xd0, 0xc1, 0x2b, 0xf4, 0x3a, 0x00,
+        0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40, 0xb6, 0x0b, 0xa7, 0x9c, 0x02, 0x6d, 0x64, 0x98,
+        0x9d, 0x73, 0x1b, 0x74, 0x21, 0x32, 0xf6, 0xb6, 0x1e, 0x6d, 0x07, 0x56, 0x0f, 0x5f, 0x14,
+        0x60, 0xf9, 0x68, 0xb5, 0xee, 0xa5, 0xf9, 0x9b, 0xa9, 0x88, 0x4c, 0x55, 0x75, 0x26, 0xa7,
+        0x84, 0xee, 0x07, 0x8a, 0xdc, 0xeb, 0x6d, 0xfe, 0x53, 0xe4, 0x38, 0xa8, 0x11, 0x1f, 0x57,
+        0xbe, 0x77, 0x51, 0xc7, 0xbe, 0x4b, 0xd5, 0x2f, 0x9c, 0x2a, 0xcd, 0x84, 0x43, 0xa1, 0x01,
+        0x26, 0xa0, 0x59, 0x02, 0x0f, 0x82, 0x58, 0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+        0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x59, 0x01, 0xe9, 0x84, 0x03,
+        0x67, 0x6b, 0x65, 0x79, 0x6d, 0x69, 0x6e, 0x74, 0xae, 0x65, 0x62, 0x72, 0x61, 0x6e, 0x64,
+        0x66, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x01, 0x65,
+        0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x66, 0x64, 0x65, 0x76,
+        0x69, 0x63, 0x65, 0x66, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x67, 0x70, 0x72, 0x6f, 0x64,
+        0x75, 0x63, 0x74, 0x65, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x68, 0x76, 0x62, 0x5f, 0x73, 0x74,
+        0x61, 0x74, 0x65, 0x65, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x6a, 0x6f, 0x73, 0x5f, 0x76, 0x65,
+        0x72, 0x73, 0x69, 0x6f, 0x6e, 0x62, 0x31, 0x32, 0x6c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61,
+        0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x66, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x6d, 0x76,
+        0x62, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x4f, 0x11, 0x22,
+        0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x6e, 0x73,
+        0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x63, 0x74,
+        0x65, 0x65, 0x70, 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c,
+        0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x62, 0x70, 0x62, 0x6f, 0x6f, 0x74, 0x6c,
+        0x6f, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x66, 0x6c, 0x6f, 0x63,
+        0x6b, 0x65, 0x64, 0x72, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x63,
+        0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x61, 0x72, 0x76, 0x65,
+        0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65,
+        0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x63, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21,
+        0x58, 0x20, 0x78, 0xa9, 0x66, 0xc0, 0xc1, 0x92, 0xc9, 0x0d, 0x74, 0xbf, 0x81, 0x99, 0xe6,
+        0x7c, 0x61, 0xb2, 0xc3, 0x41, 0x27, 0x4e, 0x92, 0xd8, 0xd8, 0xf8, 0x34, 0x43, 0x81, 0xe1,
+        0x9c, 0x5f, 0xed, 0xbb, 0x22, 0x58, 0x20, 0x80, 0x05, 0x96, 0xe5, 0x65, 0x7e, 0xa8, 0x5b,
+        0x58, 0xf7, 0x2c, 0xb8, 0x28, 0x95, 0x34, 0x7a, 0x88, 0xd5, 0xe2, 0x1c, 0x20, 0x01, 0xd7,
+        0x60, 0xfe, 0xec, 0xf1, 0x3f, 0x69, 0xfc, 0xc0, 0xa4, 0x23, 0x58, 0x21, 0x00, 0x99, 0xad,
+        0x34, 0x13, 0xf0, 0x7f, 0xaa, 0xf7, 0xda, 0xe9, 0x95, 0xfe, 0x2a, 0x36, 0xf5, 0xac, 0xbb,
+        0xad, 0x39, 0x8f, 0x3f, 0x86, 0x10, 0x39, 0x2c, 0xa9, 0x4c, 0xb9, 0xbb, 0x79, 0x10, 0x45,
+        0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xd2, 0x94, 0xcb, 0x74, 0x5f,
+        0x9c, 0xc2, 0x1e, 0x47, 0x28, 0x69, 0x85, 0x6e, 0xf2, 0x34, 0x0a, 0x62, 0x90, 0xc3, 0xb0,
+        0xc9, 0x3a, 0xb2, 0x32, 0xdc, 0x99, 0x19, 0x9b, 0x36, 0xde, 0x78, 0xed, 0x22, 0x58, 0x20,
+        0xd9, 0x81, 0x04, 0x83, 0xbb, 0x85, 0x3e, 0x3b, 0x46, 0xe8, 0xe1, 0xa3, 0x8a, 0x04, 0xb9,
+        0x3f, 0x74, 0x4e, 0x5c, 0x96, 0x21, 0x5c, 0x79, 0x0b, 0x8e, 0x4e, 0x7d, 0x61, 0x1b, 0x69,
+        0xb2, 0x46, 0x23, 0x58, 0x20, 0x2f, 0x79, 0xf7, 0xbb, 0xbb, 0x7e, 0xee, 0x15, 0x61, 0xa2,
+        0x78, 0x5f, 0x9c, 0x8c, 0xaf, 0x52, 0xcb, 0xbe, 0x24, 0x31, 0xa8, 0x95, 0x86, 0x8d, 0xed,
+        0x98, 0x80, 0x71, 0x53, 0x91, 0xb3, 0x87, 0x58, 0x40, 0x19, 0xc9, 0xc4, 0x4e, 0x8b, 0xae,
+        0x26, 0x7f, 0xdd, 0x9c, 0xac, 0xe2, 0xbf, 0xe2, 0xfb, 0x3c, 0x3f, 0xd6, 0x6f, 0x9a, 0x97,
+        0xc3, 0x2a, 0x60, 0xfe, 0x0e, 0x9f, 0x11, 0xc9, 0x04, 0xa7, 0xdf, 0xe1, 0x21, 0x1e, 0xc1,
+        0x10, 0x10, 0x64, 0xf7, 0xeb, 0xcc, 0x3a, 0x4c, 0xa6, 0xdf, 0xd8, 0xf5, 0xcc, 0x0d, 0x34,
+        0xa4, 0x32, 0xf4, 0x0a, 0xd7, 0x83, 0x1e, 0x30, 0x0d, 0x68, 0x6a, 0xb4, 0xc1};
+
+inline const std::vector<uint8_t> kCsrWithSharedUdsRoot1{
+        0x84, 0x01, 0xa0, 0x82, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x96,
+        0xf9, 0xf7, 0x16, 0xa7, 0xe2, 0x20, 0xe3, 0x6e, 0x19, 0x8e, 0xc0, 0xc4, 0x82, 0xc5, 0xca,
+        0x8d, 0x1d, 0xb4, 0xda, 0x94, 0x6d, 0xf8, 0xbc, 0x0b, 0x0e, 0xc7, 0x90, 0x83, 0x5b, 0xc3,
+        0x4b, 0x22, 0x58, 0x20, 0xed, 0xe0, 0xa1, 0x56, 0x46, 0x5b, 0xe0, 0x67, 0x2d, 0xbc, 0x08,
+        0x84, 0x6f, 0x43, 0xd0, 0x10, 0xf3, 0x70, 0x90, 0xc2, 0xbf, 0xe3, 0x6b, 0x32, 0x9f, 0xf3,
+        0xca, 0x57, 0x0f, 0xa8, 0xb9, 0xdd, 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x59, 0x01, 0x04,
+        0xa9, 0x01, 0x66, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x02, 0x67, 0x73, 0x75, 0x62, 0x6a,
+        0x65, 0x63, 0x74, 0x3a, 0x00, 0x47, 0x44, 0x50, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47,
+        0x44, 0x52, 0x58, 0x20, 0xb8, 0x96, 0x54, 0xe2, 0x2c, 0xa4, 0xd2, 0x4a, 0x9c, 0x0e, 0x45,
+        0x11, 0xc8, 0xf2, 0x63, 0xf0, 0x66, 0x0d, 0x2e, 0x20, 0x48, 0x96, 0x90, 0x14, 0xf4, 0x54,
+        0x63, 0xc4, 0xf4, 0x39, 0x30, 0x38, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x55, 0xa1, 0x3a, 0x00,
+        0x01, 0x11, 0x71, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x6e,
+        0x61, 0x6d, 0x65, 0x3a, 0x00, 0x47, 0x44, 0x54, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47,
+        0x44, 0x56, 0x41, 0x01, 0x3a, 0x00, 0x47, 0x44, 0x57, 0x58, 0x4d, 0xa5, 0x01, 0x02, 0x03,
+        0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x04, 0x25, 0x41, 0x6f, 0x6a, 0xdc, 0x88, 0x56, 0x9a,
+        0xd4, 0x39, 0x82, 0xde, 0xd1, 0xe6, 0x65, 0xd4, 0x09, 0xb8, 0x9f, 0xde, 0xbf, 0x09, 0x03,
+        0xe3, 0x9a, 0x48, 0xd4, 0x4f, 0x13, 0xaa, 0x5b, 0x22, 0x58, 0x20, 0x3a, 0xfb, 0x46, 0x2d,
+        0xe1, 0xdf, 0x34, 0x76, 0x03, 0x37, 0x1e, 0xcf, 0xea, 0xd5, 0xf6, 0xd3, 0x99, 0x3e, 0x55,
+        0x2a, 0xd1, 0x9d, 0x10, 0x21, 0xb1, 0xc8, 0x4f, 0xbd, 0xec, 0xb6, 0x67, 0x82, 0x3a, 0x00,
+        0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40, 0x10, 0xda, 0xc8, 0x8d, 0x83, 0x6d, 0xdd, 0x85,
+        0x48, 0x92, 0xdc, 0xc0, 0xc8, 0xde, 0xe4, 0x61, 0x03, 0x04, 0xfb, 0x77, 0xdf, 0xc1, 0xce,
+        0xb7, 0x9b, 0x74, 0x9a, 0x31, 0x7a, 0xca, 0xcb, 0x7c, 0x45, 0x65, 0xf5, 0xc1, 0x3b, 0x29,
+        0x53, 0x22, 0xbc, 0xda, 0xa9, 0xfa, 0x97, 0x84, 0x42, 0xfc, 0xcb, 0x36, 0xae, 0xe9, 0x67,
+        0x1c, 0xb1, 0x19, 0x42, 0x74, 0x01, 0xb1, 0x11, 0xc9, 0x7b, 0x58, 0x84, 0x43, 0xa1, 0x01,
+        0x26, 0xa0, 0x59, 0x02, 0x0f, 0x82, 0x58, 0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+        0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x59, 0x01, 0xe9, 0x84, 0x03,
+        0x67, 0x6b, 0x65, 0x79, 0x6d, 0x69, 0x6e, 0x74, 0xae, 0x65, 0x62, 0x72, 0x61, 0x6e, 0x64,
+        0x66, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x01, 0x65,
+        0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x66, 0x64, 0x65, 0x76,
+        0x69, 0x63, 0x65, 0x66, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x67, 0x70, 0x72, 0x6f, 0x64,
+        0x75, 0x63, 0x74, 0x65, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x68, 0x76, 0x62, 0x5f, 0x73, 0x74,
+        0x61, 0x74, 0x65, 0x65, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x6a, 0x6f, 0x73, 0x5f, 0x76, 0x65,
+        0x72, 0x73, 0x69, 0x6f, 0x6e, 0x62, 0x31, 0x32, 0x6c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61,
+        0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x66, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x6d, 0x76,
+        0x62, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x4f, 0x11, 0x22,
+        0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x6e, 0x73,
+        0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x63, 0x74,
+        0x65, 0x65, 0x70, 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c,
+        0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x62, 0x70, 0x62, 0x6f, 0x6f, 0x74, 0x6c,
+        0x6f, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x66, 0x6c, 0x6f, 0x63,
+        0x6b, 0x65, 0x64, 0x72, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x63,
+        0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x61, 0x72, 0x76, 0x65,
+        0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65,
+        0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x63, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21,
+        0x58, 0x20, 0xf6, 0x86, 0x74, 0x7d, 0x1a, 0x83, 0x75, 0xec, 0x8c, 0xf9, 0x3a, 0xa9, 0x20,
+        0x88, 0xe5, 0xca, 0x24, 0x34, 0x24, 0xbf, 0x89, 0xe7, 0xdb, 0x44, 0xc3, 0x6e, 0xdd, 0x5d,
+        0x1a, 0xe1, 0xf0, 0xd8, 0x22, 0x58, 0x20, 0xae, 0xcb, 0x01, 0x2e, 0x73, 0xac, 0xb5, 0x52,
+        0x0e, 0x73, 0x15, 0xd8, 0x9d, 0x78, 0x64, 0x10, 0x35, 0x41, 0x0e, 0xc9, 0x7d, 0x9a, 0x11,
+        0xa3, 0xed, 0x7f, 0x53, 0xa6, 0xff, 0xc4, 0xad, 0x61, 0x23, 0x58, 0x20, 0x5a, 0xd2, 0xc5,
+        0xd0, 0x58, 0x2e, 0x94, 0x93, 0xd7, 0xa4, 0x2d, 0x5b, 0x12, 0x43, 0x52, 0x93, 0xc3, 0x95,
+        0x91, 0xac, 0x6a, 0xa3, 0x31, 0x08, 0xda, 0x33, 0x6a, 0xce, 0x7e, 0x8e, 0xae, 0xb1, 0xa6,
+        0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x8f, 0xb1, 0x85, 0xa5, 0xf5, 0x68,
+        0x74, 0xfc, 0x8a, 0x87, 0x2b, 0x13, 0xea, 0xf7, 0xff, 0x82, 0x6d, 0xcf, 0xc3, 0xea, 0x04,
+        0x80, 0x40, 0xe5, 0xcb, 0x80, 0xdb, 0x07, 0x8b, 0x36, 0x8c, 0x29, 0x22, 0x58, 0x20, 0x6a,
+        0x8c, 0x52, 0x3f, 0xf7, 0x26, 0xb3, 0xf9, 0xa8, 0x91, 0x08, 0x4e, 0xec, 0x7a, 0x03, 0x16,
+        0x1c, 0xab, 0x12, 0xcd, 0x8b, 0x05, 0x77, 0x33, 0x16, 0x1c, 0x80, 0x99, 0x79, 0x14, 0x6a,
+        0x5c, 0x23, 0x58, 0x21, 0x00, 0xd0, 0x0a, 0xa2, 0xaa, 0x27, 0x62, 0x10, 0x24, 0x0c, 0x74,
+        0x34, 0xe7, 0x06, 0xb3, 0x4d, 0x33, 0x9c, 0x86, 0xa6, 0x62, 0xb9, 0x0f, 0x1a, 0x4b, 0xe2,
+        0x8b, 0x45, 0x0a, 0xc9, 0xe3, 0x43, 0x28, 0x58, 0x40, 0xea, 0xe3, 0xd3, 0xd9, 0x7f, 0x4e,
+        0x08, 0x8a, 0x5b, 0xb9, 0xef, 0x28, 0x5a, 0xe0, 0x02, 0x40, 0xf5, 0x68, 0x49, 0x8b, 0xa7,
+        0xf7, 0x9d, 0xa3, 0xb3, 0x37, 0x72, 0x79, 0xa9, 0x32, 0x47, 0xf6, 0x8d, 0x5d, 0x08, 0xe7,
+        0xec, 0x00, 0x19, 0x09, 0x6f, 0x0a, 0x4d, 0x7c, 0x62, 0x6c, 0x2b, 0xaa, 0x33, 0x61, 0xe5,
+        0xa5, 0x3f, 0x2a, 0xfe, 0xcc, 0xdf, 0x8e, 0x62, 0x1c, 0x31, 0xe1, 0x56, 0x6b};
+
+inline const std::vector<uint8_t> kCsrWithSharedUdsRoot2{
+        0x84, 0x01, 0xa0, 0x82, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x96,
+        0xf9, 0xf7, 0x16, 0xa7, 0xe2, 0x20, 0xe3, 0x6e, 0x19, 0x8e, 0xc0, 0xc4, 0x82, 0xc5, 0xca,
+        0x8d, 0x1d, 0xb4, 0xda, 0x94, 0x6d, 0xf8, 0xbc, 0x0b, 0x0e, 0xc7, 0x90, 0x83, 0x5b, 0xc3,
+        0x4b, 0x22, 0x58, 0x20, 0xed, 0xe0, 0xa1, 0x56, 0x46, 0x5b, 0xe0, 0x67, 0x2d, 0xbc, 0x08,
+        0x84, 0x6f, 0x43, 0xd0, 0x10, 0xf3, 0x70, 0x90, 0xc2, 0xbf, 0xe3, 0x6b, 0x32, 0x9f, 0xf3,
+        0xca, 0x57, 0x0f, 0xa8, 0xb9, 0xdd, 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x59, 0x01, 0x04,
+        0xa9, 0x01, 0x66, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x02, 0x67, 0x73, 0x75, 0x62, 0x6a,
+        0x65, 0x63, 0x74, 0x3a, 0x00, 0x47, 0x44, 0x50, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47,
+        0x44, 0x52, 0x58, 0x20, 0xb8, 0x96, 0x54, 0xe2, 0x2c, 0xa4, 0xd2, 0x4a, 0x9c, 0x0e, 0x45,
+        0x11, 0xc8, 0xf2, 0x63, 0xf0, 0x66, 0x0d, 0x2e, 0x20, 0x48, 0x96, 0x90, 0x14, 0xf4, 0x54,
+        0x63, 0xc4, 0xf4, 0x39, 0x30, 0x38, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x55, 0xa1, 0x3a, 0x00,
+        0x01, 0x11, 0x71, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x6e,
+        0x61, 0x6d, 0x65, 0x3a, 0x00, 0x47, 0x44, 0x54, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47,
+        0x44, 0x56, 0x41, 0x01, 0x3a, 0x00, 0x47, 0x44, 0x57, 0x58, 0x4d, 0xa5, 0x01, 0x02, 0x03,
+        0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x2d, 0xbd, 0x92, 0x58, 0xc8, 0xcd, 0xc3, 0xc5, 0x14,
+        0xe3, 0x6e, 0x5f, 0xab, 0x71, 0x41, 0x46, 0x83, 0xb4, 0x3e, 0x82, 0xdb, 0xe7, 0x7d, 0x27,
+        0xe5, 0x26, 0x36, 0x94, 0xcb, 0x4c, 0x72, 0x8f, 0x22, 0x58, 0x20, 0xbf, 0xa2, 0xa7, 0x15,
+        0x46, 0x5a, 0xea, 0xa8, 0xc7, 0xad, 0x22, 0x61, 0x9c, 0xba, 0x87, 0x70, 0x65, 0x64, 0x11,
+        0x05, 0x8a, 0x58, 0x8c, 0x0c, 0x25, 0xc7, 0xf8, 0x5f, 0xfc, 0x4a, 0xee, 0xa1, 0x3a, 0x00,
+        0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40, 0x43, 0xba, 0xff, 0xdb, 0xbb, 0xa9, 0x9e, 0x8f,
+        0x06, 0xdf, 0x33, 0xa0, 0x3f, 0x30, 0xc3, 0x64, 0x84, 0x32, 0xb5, 0x2a, 0x06, 0x53, 0x13,
+        0x70, 0xbe, 0xa3, 0x0b, 0x4d, 0xbe, 0x8d, 0x8c, 0x90, 0xde, 0x6c, 0x1d, 0xa8, 0xea, 0x40,
+        0xd5, 0x17, 0xa1, 0xea, 0x62, 0x95, 0x37, 0x64, 0x92, 0xc3, 0xc4, 0xef, 0xd7, 0xcf, 0x87,
+        0x0c, 0x9a, 0xd2, 0x5c, 0x10, 0x1d, 0x00, 0x2e, 0xe4, 0xe9, 0x1f, 0x84, 0x43, 0xa1, 0x01,
+        0x26, 0xa0, 0x59, 0x02, 0x10, 0x82, 0x58, 0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+        0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x59, 0x01, 0xea, 0x84, 0x03,
+        0x67, 0x6b, 0x65, 0x79, 0x6d, 0x69, 0x6e, 0x74, 0xae, 0x65, 0x62, 0x72, 0x61, 0x6e, 0x64,
+        0x66, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x01, 0x65,
+        0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x66, 0x64, 0x65, 0x76,
+        0x69, 0x63, 0x65, 0x66, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x67, 0x70, 0x72, 0x6f, 0x64,
+        0x75, 0x63, 0x74, 0x65, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x68, 0x76, 0x62, 0x5f, 0x73, 0x74,
+        0x61, 0x74, 0x65, 0x65, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x6a, 0x6f, 0x73, 0x5f, 0x76, 0x65,
+        0x72, 0x73, 0x69, 0x6f, 0x6e, 0x62, 0x31, 0x32, 0x6c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61,
+        0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x66, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x6d, 0x76,
+        0x62, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x4f, 0x11, 0x22,
+        0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x6e, 0x73,
+        0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x63, 0x74,
+        0x65, 0x65, 0x70, 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c,
+        0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x62, 0x70, 0x62, 0x6f, 0x6f, 0x74, 0x6c,
+        0x6f, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x66, 0x6c, 0x6f, 0x63,
+        0x6b, 0x65, 0x64, 0x72, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x63,
+        0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x61, 0x72, 0x76, 0x65,
+        0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65,
+        0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x63, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21,
+        0x58, 0x20, 0xad, 0xd2, 0x8c, 0xcc, 0xfb, 0x22, 0xd8, 0x5a, 0x3b, 0x9d, 0x22, 0x58, 0xb3,
+        0x7c, 0xcc, 0xa5, 0x22, 0x46, 0x86, 0x2b, 0x29, 0x87, 0x49, 0xdd, 0xe4, 0x2c, 0xb4, 0x3f,
+        0xf2, 0x4e, 0x6a, 0xed, 0x22, 0x58, 0x20, 0xe9, 0x34, 0x28, 0x54, 0x21, 0x7e, 0x88, 0x34,
+        0x82, 0x0d, 0x0f, 0x14, 0x5b, 0xec, 0x61, 0xc4, 0xf2, 0xa4, 0xef, 0xf8, 0x17, 0xeb, 0xeb,
+        0x05, 0x01, 0x36, 0x14, 0x52, 0xc7, 0xc2, 0xd8, 0xd3, 0x23, 0x58, 0x21, 0x00, 0xd9, 0xb4,
+        0x13, 0xd0, 0x86, 0x31, 0x5e, 0x97, 0xc2, 0x54, 0x03, 0x72, 0x80, 0x6f, 0x14, 0x53, 0xbe,
+        0x2e, 0xe5, 0x1b, 0x02, 0x1a, 0x62, 0x1a, 0x88, 0xe8, 0xa2, 0xde, 0xd0, 0x7d, 0xf6, 0x53,
+        0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xca, 0x7d, 0x6e, 0xb5, 0x78,
+        0x99, 0x9e, 0x66, 0xf4, 0x5d, 0xfe, 0xd5, 0x92, 0xe3, 0x30, 0xf5, 0xd5, 0xc2, 0x82, 0xf2,
+        0x6d, 0x58, 0x16, 0x26, 0xa5, 0xe7, 0xfc, 0x62, 0x8f, 0xf3, 0x61, 0x56, 0x22, 0x58, 0x20,
+        0x9f, 0x42, 0x22, 0x11, 0x1c, 0x45, 0x5c, 0x3a, 0x30, 0x95, 0xb4, 0xb3, 0x63, 0x26, 0x09,
+        0xfc, 0x2e, 0x6e, 0x99, 0xdd, 0x44, 0x37, 0x34, 0xa9, 0x68, 0x42, 0xf5, 0x91, 0x40, 0xae,
+        0xfa, 0x52, 0x23, 0x58, 0x21, 0x00, 0xe2, 0x3b, 0xaa, 0x88, 0xfc, 0xec, 0x23, 0xe7, 0x93,
+        0x91, 0x04, 0x8e, 0xae, 0xa7, 0x44, 0xb4, 0x5e, 0x46, 0xe8, 0x91, 0x59, 0x3e, 0x43, 0x13,
+        0x82, 0x8e, 0xa1, 0xee, 0x47, 0xbd, 0x13, 0x27, 0x58, 0x40, 0x43, 0x1d, 0xc8, 0x35, 0x44,
+        0xbf, 0xd5, 0x06, 0x2c, 0xac, 0x18, 0x3c, 0xbb, 0xc6, 0x77, 0x99, 0x2f, 0x4e, 0x71, 0xcd,
+        0x7a, 0x9b, 0x93, 0xc7, 0x08, 0xa3, 0x71, 0x89, 0xb5, 0xb2, 0x04, 0xbe, 0x69, 0x22, 0xf3,
+        0x66, 0xb8, 0xa9, 0xc6, 0x5e, 0x7c, 0x45, 0xf6, 0x2f, 0x8a, 0xa9, 0x3e, 0xee, 0x6f, 0x92,
+        0x2a, 0x9c, 0x91, 0xe2, 0x1d, 0x4a, 0x4e, 0x4a, 0xb4, 0xcc, 0x87, 0xd2, 0x85, 0x5f};
+
+const RpcHardwareInfo kRpcHardwareInfo = {.versionNumber = 3};
+
 inline bool equal_byte_views(const byte_view& view1, const byte_view& view2) {
     return std::equal(view1.begin(), view1.end(), view2.begin(), view2.end());
 }
@@ -258,5 +898,186 @@
     EXPECT_THAT(eekPubY, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_Y).value_or(empty)));
 }
 
+TEST(RemoteProvUtilsTest, validateBccDegenerate) {
+    auto [bcc, _, errMsg] = cppbor::parse(kDegenerateBcc);
+    ASSERT_TRUE(bcc) << "Error: " << errMsg;
+
+    EXPECT_TRUE(validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr16,
+                            /*allowAnyMode=*/false, /*allowDegenerate=*/true,
+                            DEFAULT_INSTANCE_NAME));
+    EXPECT_FALSE(validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr16,
+                             /*allowAnyMode=*/false, /*allowDegenerate=*/false,
+                             DEFAULT_INSTANCE_NAME));
+}
+
+TEST(RemoteProvUtils, validateDiceChainProper) {
+    auto result = isCsrWithProperDiceChain(kCsrWithUdsCerts, DEFAULT_INSTANCE_NAME);
+    ASSERT_TRUE(result) << result.message();
+    ASSERT_TRUE(*result) << "DICE Chain is degenerate";
+}
+
+TEST(RemoteProvUtils, validateDiceChainDegenerate) {
+    auto result = isCsrWithProperDiceChain(kCsrWithDegenerateDiceChain, DEFAULT_INSTANCE_NAME);
+    ASSERT_TRUE(result) << result.message();
+    ASSERT_FALSE(*result) << "DICE Chain is proper";
+}
+
+TEST(RemoteProvUtils, csrHasUdsCerts) {
+    auto csr = hwtrust::Csr::validate(kCsrWithUdsCerts, hwtrust::DiceChain::Kind::kVsr16,
+                                      false /*isFactory*/, false /*allowAnyMode*/,
+                                      deviceSuffix(DEFAULT_INSTANCE_NAME));
+    ASSERT_TRUE(csr.ok()) << csr.error().message();
+    ASSERT_TRUE(csr->hasUdsCerts());
+}
+
+TEST(RemoteProvUtils, csrDoesntHaveUdsCerts) {
+    auto csr = hwtrust::Csr::validate(kCsrWithoutUdsCerts, hwtrust::DiceChain::Kind::kVsr16,
+                                      false /*isFactory*/, false /*allowAnyMode*/,
+                                      deviceSuffix(DEFAULT_INSTANCE_NAME));
+    ASSERT_TRUE(csr.ok()) << csr.error().message();
+    ASSERT_FALSE(csr->hasUdsCerts());
+}
+
+TEST(RemoteProvUtils, csrHasCorrectChallenge) {
+    auto csr = hwtrust::Csr::validate(kCsrWithoutUdsCerts, hwtrust::DiceChain::Kind::kVsr16,
+                                      false /*isFactory*/, false /*allowAnyMode*/,
+                                      deviceSuffix(DEFAULT_INSTANCE_NAME));
+    ASSERT_TRUE(csr.ok()) << csr.error().message();
+
+    auto equal = csr->compareChallenge(kChallenge);
+    ASSERT_TRUE(equal.ok()) << equal.error().message();
+
+    ASSERT_TRUE(*equal) << kErrorChallengeMismatch;
+
+    auto zeroes = std::vector<uint8_t>(32, 0);
+    auto notEqual = csr->compareChallenge(zeroes);
+    ASSERT_TRUE(notEqual.ok()) << notEqual.error().message();
+
+    ASSERT_FALSE(*notEqual) << "ERROR: challenges are not different";
+}
+
+TEST(RemoteProvUtils, csrHasCorrectKeysToSign) {
+    auto csr = hwtrust::Csr::validate(kCsrWithoutUdsCerts, hwtrust::DiceChain::Kind::kVsr16,
+                                      false /*isFactory*/, false /*allowAnyMode*/,
+                                      deviceSuffix(DEFAULT_INSTANCE_NAME));
+    ASSERT_TRUE(csr.ok()) << csr.error().message();
+
+    auto equal = csr->compareKeysToSign(kKeysToSignForCsrWithoutUdsCerts);
+    ASSERT_TRUE(equal.ok()) << equal.error().message();
+    ASSERT_TRUE(*equal) << kErrorKeysToSignMismatch;
+
+    auto zeroes = std::vector<uint8_t>(kKeysToSignForCsrWithoutUdsCerts.size(), 0);
+    auto notEqual = csr->compareKeysToSign(zeroes);
+    ASSERT_TRUE(notEqual.ok()) << notEqual.error().message();
+    ASSERT_FALSE(*notEqual) << kErrorKeysToSignMismatch;
+}
+
+TEST(RemoteProvUtilsTest, allowDegenerateDiceChainWhenDegenerate) {
+    auto [keysToSignPtr, _, errMsg] = cppbor::parse(kKeysToSignForCsrWithDegenerateDiceChain);
+    ASSERT_TRUE(keysToSignPtr) << "Error: " << errMsg;
+
+    const auto keysToSign = keysToSignPtr->asArray();
+    auto csr = verifyFactoryCsr(*keysToSign, kCsrWithDegenerateDiceChain, kRpcHardwareInfo,
+                                DEFAULT_INSTANCE_NAME, kChallenge,
+                                /*allowDegenerate=*/true, /*requireUdsCerts=*/false);
+    ASSERT_TRUE(csr) << csr.message();
+}
+
+TEST(RemoteProvUtilsTest, disallowDegenerateDiceChainWhenDegenerate) {
+    auto [keysToSignPtr, _, errMsg] = cppbor::parse(kKeysToSignForCsrWithDegenerateDiceChain);
+    ASSERT_TRUE(keysToSignPtr) << "Error: " << errMsg;
+
+    const auto keysToSign = keysToSignPtr->asArray();
+    auto csr = verifyFactoryCsr(*keysToSign, kCsrWithDegenerateDiceChain, kRpcHardwareInfo,
+                                DEFAULT_INSTANCE_NAME, kChallenge,
+                                /*allowDegenerate=*/false, /*requireUdsCerts=*/false);
+    ASSERT_FALSE(csr);
+    ASSERT_THAT(csr.message(), testing::HasSubstr(kErrorDiceChainIsDegenerate));
+}
+
+TEST(RemoteProvUtilsTest, requireUdsCertsWhenPresent) {
+    auto [keysToSignPtr, _, errMsg] = cppbor::parse(kKeysToSignForCsrWithUdsCerts);
+    ASSERT_TRUE(keysToSignPtr) << "Error: " << errMsg;
+
+    const auto keysToSign = keysToSignPtr->asArray();
+    auto csr = verifyFactoryCsr(*keysToSign, kCsrWithUdsCerts, kRpcHardwareInfo,
+                                DEFAULT_INSTANCE_NAME, kChallenge,
+                                /*allowDegenerate=*/false, /*requireUdsCerts=*/true);
+    ASSERT_TRUE(csr) << csr.message();
+}
+
+TEST(RemoteProvUtilsTest, dontRequireUdsCertsWhenPresent) {
+    auto [keysToSignPtr, _, errMsg] = cppbor::parse(kKeysToSignForCsrWithUdsCerts);
+    ASSERT_TRUE(keysToSignPtr) << "Error: " << errMsg;
+
+    const auto* keysToSign = keysToSignPtr->asArray();
+    auto csr = verifyFactoryCsr(*keysToSign, kCsrWithUdsCerts, kRpcHardwareInfo,
+                                DEFAULT_INSTANCE_NAME, kChallenge,
+                                /*allowDegenerate=*/false, /*requireUdsCerts=*/false);
+    ASSERT_TRUE(csr) << csr.message();
+}
+
+TEST(RemoteProvUtilsTest, requireUdsCertsWhenNotPresent) {
+    auto csr = verifyFactoryCsr(/*keysToSign=*/Array(), kCsrWithoutUdsCerts, kRpcHardwareInfo,
+                                DEFAULT_INSTANCE_NAME, kChallenge, /*allowDegenerate=*/false,
+                                /*requireUdsCerts=*/true);
+    ASSERT_FALSE(csr);
+    ASSERT_THAT(csr.message(), testing::HasSubstr(kErrorUdsCertsAreRequired));
+}
+
+TEST(RemoteProvUtilsTest, dontRequireUdsCertsWhenNotPresent) {
+    auto [keysToSignPtr, _, errMsg] = cppbor::parse(kKeysToSignForCsrWithoutUdsCerts);
+    ASSERT_TRUE(keysToSignPtr) << "Error: " << errMsg;
+
+    const auto* keysToSign = keysToSignPtr->asArray();
+    auto csr = verifyFactoryCsr(*keysToSign, kCsrWithoutUdsCerts, kRpcHardwareInfo,
+                                DEFAULT_INSTANCE_NAME, kChallenge,
+                                /*allowDegenerate=*/false, /*requireUdsCerts=*/false);
+    ASSERT_TRUE(csr) << csr.message();
+}
+
+TEST(RemoteProvUtilsTest, compareRootPublicKeysInDiceChains) {
+    ASSERT_NE(kCsrWithSharedUdsRoot1, kCsrWithSharedUdsRoot2);
+    ASSERT_NE(kCsrWithUdsCerts, kCsrWithSharedUdsRoot1);
+
+    auto equal = compareRootPublicKeysInDiceChains(kCsrWithSharedUdsRoot1, DEFAULT_INSTANCE_NAME,
+                                                   kCsrWithSharedUdsRoot2, DEFAULT_INSTANCE_NAME);
+    ASSERT_TRUE(equal) << equal.message();
+    ASSERT_TRUE(*equal) << "Root public keys in DICE chains do not match.";
+
+    auto notEqual = compareRootPublicKeysInDiceChains(kCsrWithSharedUdsRoot1, DEFAULT_INSTANCE_NAME,
+                                                      kCsrWithUdsCerts, DEFAULT_INSTANCE_NAME);
+    ASSERT_TRUE(notEqual) << notEqual.message();
+    ASSERT_FALSE(*notEqual) << "Root public keys in DICE chains match.";
+}
+
+TEST(RemoteProvUtilsTest, componentNameInLeafCertificateOfDiceChainContainsKeyMint) {
+    auto result = verifyComponentNameInKeyMintDiceChain(kCsrWithKeyMintInComponentName);
+    ASSERT_TRUE(result) << result.message();
+    ASSERT_TRUE(*result) << "Leaf Certificate in CSR does not contain 'keymint' in component name";
+
+    auto result2 = verifyComponentNameInKeyMintDiceChain(kCsrWithUdsCerts);
+    ASSERT_TRUE(result2) << result2.message();
+    ASSERT_FALSE(*result2) << "Leaf Certificate in CSR contains 'keymint' in component name";
+}
+
+TEST(RemoteProvUtilsTest, checkModeOnCertificatesInDiceChain) {
+    auto hasNonNormalMode = hasNonNormalModeInDiceChain(kCsrWithDebugMode, DEFAULT_INSTANCE_NAME);
+    ASSERT_TRUE(hasNonNormalMode) << hasNonNormalMode.message();
+    ASSERT_TRUE(*hasNonNormalMode);
+
+    auto hasNonNormalModeInDiceChain2 =
+            hasNonNormalModeInDiceChain(kCsrWithUdsCerts, DEFAULT_INSTANCE_NAME);
+    ASSERT_TRUE(hasNonNormalModeInDiceChain2) << hasNonNormalModeInDiceChain2.message();
+    ASSERT_FALSE(*hasNonNormalModeInDiceChain2);
+}
+
+TEST(RemoteProvUtilsTest, parseFullyQualifiedInstanceNames) {
+    ASSERT_EQ(deviceSuffix(RKPVM_INSTANCE_NAME), "avf");
+    ASSERT_EQ(deviceSuffix(DEFAULT_INSTANCE_NAME), "default");
+    ASSERT_EQ(deviceSuffix("default"), "default");
+    ASSERT_EQ(deviceSuffix("//the/last/one"), "one");
+}
+
 }  // namespace
 }  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/rkp/OWNERS b/security/rkp/OWNERS
index d25977f..fd43089 100644
--- a/security/rkp/OWNERS
+++ b/security/rkp/OWNERS
@@ -2,4 +2,4 @@
 
 jbires@google.com
 sethmo@google.com
-trong@google.com
+vikramgaur@google.com
diff --git a/security/rkp/README.md b/security/rkp/README.md
index 67cf72e..43a00fb 100644
--- a/security/rkp/README.md
+++ b/security/rkp/README.md
@@ -31,12 +31,13 @@
 1.  (Preferred, recommended) The device OEM extracts the UDS\_pub from each
     device they manufacture and uploads the public keys to a backend server.
 
-1.  The device OEM signs the UDS\_pub and stores the certificates on the device
-    rather than uploading a UDS\_pub for every device immediately. However,
-    there are many disadvantages and costs associated with this option as the
-    OEM will need to pass a security audit of their factory's physical security,
-    CA and HSM configuration, and incident response processes before the OEM's
-    public key is registered with the provisioning server.
+1.  The device OEM certifies the UDS\_pub using an x.509 certificate chain
+    then stores the chain on the device rather than uploading a UDS\_pub for
+    every device immediately. However, there are many disadvantages and costs
+    associated with this option as the OEM will need to pass a security audit
+    of their factory's physical security, CA and HSM configuration, and
+    incident response processes before the OEM's public key is registered with
+    the provisioning server.
 
 Note that in the full elaboration of this plan, UDS\_pub is not the key used to
 sign certificate requests. Instead, UDS\_pub is just the first public key in a
@@ -124,6 +125,53 @@
 choice for algorithm implies the implementor should also choose the P256 public
 key group further down in the COSE structure.
 
+## UDS certificates
+
+As noted in the section [General approach](#general-approach), the UDS\_pub may
+be authenticated by an OEM using an x.509 certificate chain. Additionally,
+[RKP Phase 3](#phases) depends on the chip vendor signing the UDS\_pub and
+issuing an x.509 certificate chain. This section describes the requirements for
+both the signing keys and the resulting certificate chain.
+
+### X.509 Certificates
+
+X.509v3 public key certificates are the only supported mechanism for
+authenticating a UDS\_pub. Certificates must be formatted according to
+[RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280), and certificate
+chains must satisfy the certificate path validation described in the RFC. RFC
+5280 covers most requirements for the chain, but this specification has some
+additional requirements that must be met for the certificates:
+
+*   [`BasicConstraints`](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.9)
+    *   All CA certificates must include this as a critical extension.
+    *   `pathLenConstraint` must be set correctly in each CA certificate to
+        limit the maximum chain length.
+    *   `cA` must be set to true for all certificates except the leaf
+        certificate.
+    *   `BasicConstraints` must be absent for the leaf/UDS certificate.
+    *   Consider the chain `root -> intermediate -> UDS_pub`. In such a chain,
+        `BasicConstraints` must be:
+        *   `{ cA: TRUE, pathLenConstraint: 1}` for the root certificate
+        *   `{ cA: TRUE, pathLenConstraint: 0}` for the intermediate certificate
+        *   Absent for the UDS certificate
+*   [`KeyUsage`](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3)
+    *   All certificates in a UDS certificate chain must include this as a
+        critical extension.
+    *   CA certificates must set `KeyUsage` to only `keyCertSign`.
+    *   The UDS certificate must set `KeyUsage` to only `digitalSignature`.
+
+### Supported Algorithms
+
+UDS certificates must be signed using one of the following allowed algorithms:
+
+*   `ecdsa-with-SHA256`
+    ([RFC 5758](https://www.rfc-editor.org/rfc/rfc5758#section-3.2))
+    *   Note: this algorithm is only usable with ECDSA P-256 keys
+*   `ecdsa-with-SHA384`
+    ([RFC 5758](https://www.rfc-editor.org/rfc/rfc5758#section-3.2))
+    *   Note: this algorithm is only usable with ECDSA P-384 keys
+*   `id-Ed25519` ([RFC 8410](https://www.rfc-editor.org/rfc/rfc8410#section-3))
+
 ## Design
 
 ### Certificate provisioning flow
diff --git a/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
index 3c43238..c519086 100644
--- a/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
+++ b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
@@ -52,7 +52,8 @@
 ; example, this could be provided by the hardware vendor, who certifies all of their chips.
 ; The SignerName is a free-form string describing who generated the signature. The root
 ; certificate will need to be communicated to the verifier out of band, along with the
-; SignerName that is expected for the given root certificate.
+; SignerName that is expected for the given root certificate. UDS certificate
+; requirements are defined in https://android.googlesource.com/platform/hardware/interfaces/+/main/security/rkp/README.md#uds-certificates.
 UdsCerts = {
     * SignerName => UdsCertChain
 }
@@ -62,9 +63,13 @@
 SignerName = tstr
 
 UdsCertChain = [
-    2* X509Certificate      ; Root -> ... -> Leaf. "Root" is the vendor self-signed
-                            ; cert, "Leaf" contains UDS_Public. There may also be
-                            ; intermediate certificates between Root and Leaf.
+    + X509Certificate       ; Root -> ... -> Leaf. "Root" is the vendor self-signed
+                            ; cert, "Leaf" contains UDS_Pub. It's recommended to
+                            ; have at least 3 certificates in the chain.
+                            ; The Root certificate is recommended to be generated in an air-gapped,
+                            ; HSM-based secure environment. The intermediate signing keys may be
+                            ; online, and should be rotated regularly (e.g. annually). Additionally,
+                            ; the intermediate certificates may contain product family identifiers.
 ]
 
 ; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or EdDSA)
@@ -73,7 +78,7 @@
 ; The DICE Chain contains measurements about the device firmware.
 ; The first entry in the DICE Chain is the UDS_Pub, encoded as a COSE_key. All entries
 ; after the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN)
-; Note that there is no DiceChainEntry for UDS_pub, only a "bare" COSE_key.
+; Note that there is no DiceChainEntry for UDS_Pub, only a "bare" COSE_key.
 DiceCertChain = [
     PubKeyEd25519 / PubKeyECDSA256 / PubKeyECDSA384,  ; UDS_Pub
     + DiceChainEntry,               ; First CDI_Certificate -> Last CDI_Certificate
diff --git a/security/rkp/aidl/vts/functional/Android.bp b/security/rkp/aidl/vts/functional/Android.bp
index 2cce8db..3bc8c9e 100644
--- a/security/rkp/aidl/vts/functional/Android.bp
+++ b/security/rkp/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
diff --git a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 2dbc73f..7ef445e 100644
--- a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -35,6 +35,7 @@
 #include <remote_prov/remote_prov_utils.h>
 #include <optional>
 #include <set>
+#include <string_view>
 #include <vector>
 
 #include "KeyMintAidlTestBase.h"
@@ -55,10 +56,7 @@
 
 constexpr uint8_t MIN_CHALLENGE_SIZE = 0;
 constexpr uint8_t MAX_CHALLENGE_SIZE = 64;
-const string DEFAULT_INSTANCE_NAME =
-        "android.hardware.security.keymint.IRemotelyProvisionedComponent/default";
-const string RKP_VM_INSTANCE_NAME =
-        "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf";
+
 const string KEYMINT_STRONGBOX_INSTANCE_NAME =
         "android.hardware.security.keymint.IKeyMintDevice/strongbox";
 
@@ -153,28 +151,24 @@
     return corruptChain.encode();
 }
 
-string device_suffix(const string& name) {
-    size_t pos = name.find('/');
-    if (pos == string::npos) {
-        return name;
-    }
-    return name.substr(pos + 1);
+template <class T>
+auto getHandle(const string& serviceName) {
+    ::ndk::SpAIBinder binder(AServiceManager_waitForService(serviceName.c_str()));
+    return T::fromBinder(binder);
 }
 
-bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
-    string rp_suffix = device_suffix(rp_name);
+std::shared_ptr<IKeyMintDevice> matchingKeyMintDevice(const string& rpcName) {
+    auto rpcSuffix = deviceSuffix(rpcName);
 
-    vector<string> km_names = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
-    for (const string& km_name : km_names) {
+    vector<string> kmNames = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
+    for (const string& kmName : kmNames) {
         // If the suffix of the KeyMint instance equals the suffix of the
         // RemotelyProvisionedComponent instance, assume they match.
-        if (device_suffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
-            ::ndk::SpAIBinder binder(AServiceManager_waitForService(km_name.c_str()));
-            *keyMint = IKeyMintDevice::fromBinder(binder);
-            return true;
+        if (deviceSuffix(kmName) == rpcSuffix && AServiceManager_isDeclared(kmName.c_str())) {
+            getHandle<IKeyMintDevice>(kmName);
         }
     }
-    return false;
+    return nullptr;
 }
 
 }  // namespace
@@ -183,19 +177,19 @@
   public:
     virtual void SetUp() override {
         if (AServiceManager_isDeclared(GetParam().c_str())) {
-            ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
-            provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
+            provisionable_ = getHandle<IRemotelyProvisionedComponent>(GetParam());
         }
         ASSERT_NE(provisionable_, nullptr);
         auto status = provisionable_->getHardwareInfo(&rpcHardwareInfo);
-        if (GetParam() == RKP_VM_INSTANCE_NAME) {
+        isRkpVmInstance_ = GetParam() == RKPVM_INSTANCE_NAME;
+        if (isRkpVmInstance_) {
             if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
                 GTEST_SKIP() << "The RKP VM is not supported on this system.";
             }
-            int apiLevel = get_vsr_api_level();
-            if (apiLevel < __ANDROID_API_V__) {
-                GTEST_SKIP() << "The RKP VM is supported only on V+ devices. Vendor API level: "
-                             << apiLevel;
+            int vendorApiLevel = get_vendor_api_level();
+            if (vendorApiLevel < __ANDROID_API_V__) {
+                GTEST_SKIP() << "The RKP VM is supported only on vendor API level >= 202404. This "
+                             << "device has vendor API level: " << vendorApiLevel;
             }
         }
         ASSERT_TRUE(status.isOk());
@@ -209,6 +203,7 @@
   protected:
     std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
     RpcHardwareInfo rpcHardwareInfo;
+    bool isRkpVmInstance_;
 };
 
 /**
@@ -218,14 +213,12 @@
     std::set<std::string> uniqueIds;
     for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
         ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
-        ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
-        std::shared_ptr<IRemotelyProvisionedComponent> rpc =
-                IRemotelyProvisionedComponent::fromBinder(binder);
+        auto rpc = getHandle<IRemotelyProvisionedComponent>(hal);
         ASSERT_NE(rpc, nullptr);
 
         RpcHardwareInfo hwInfo;
         auto status = rpc->getHardwareInfo(&hwInfo);
-        if (hal == RKP_VM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+        if (hal == RKPVM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
             GTEST_SKIP() << "The RKP VM is not supported on this system.";
         }
         ASSERT_TRUE(status.isOk());
@@ -245,11 +238,91 @@
  * on the device.
  */
 // @VsrTest = 3.10-015
+// @VsrTest = 3.10-018.001
 TEST(NonParameterizedTests, requireDiceOnDefaultInstanceIfStrongboxPresent) {
-    int vsr_api_level = get_vsr_api_level();
-    if (vsr_api_level < 35) {
-        GTEST_SKIP() << "Applies only to VSR API level 35 or newer, this device is: "
-                     << vsr_api_level;
+    int vendor_api_level = get_vendor_api_level();
+    if (vendor_api_level < __ANDROID_API_V__) {
+        GTEST_SKIP() << "Applies only to vendor API level >= 202404, but this device is: "
+                     << vendor_api_level;
+    }
+
+    if (!AServiceManager_isDeclared(KEYMINT_STRONGBOX_INSTANCE_NAME.c_str())) {
+        GTEST_SKIP() << "Strongbox is not present on this device.";
+    }
+
+    auto rpc = getHandle<IRemotelyProvisionedComponent>(DEFAULT_INSTANCE_NAME);
+    ASSERT_NE(rpc, nullptr);
+
+    bytevec challenge = randomBytes(64);
+    bytevec csr;
+    auto status = rpc->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
+    EXPECT_TRUE(status.isOk()) << status.getDescription();
+
+    auto result = isCsrWithProperDiceChain(csr, DEFAULT_INSTANCE_NAME);
+    ASSERT_TRUE(result) << result.message();
+    ASSERT_TRUE(*result);
+}
+
+/**
+ * Verify that if a protected VM (also called `avf` or RKP VM) implementation exists, then the
+ * protected VM and the primary KeyMint (also called 'default') implementation's DICE certificate
+ * chain has the same root public key, i.e., the same UDS public key
+ */
+// @VsrTest = 7.1-003.001
+TEST(NonParameterizedTests, equalUdsPubInDiceCertChainForRkpVmAndPrimaryKeyMintInstances) {
+    int vendorApiLevel = get_vendor_api_level();
+    if (vendorApiLevel < 202504 && !AServiceManager_isDeclared(RKPVM_INSTANCE_NAME.c_str())) {
+        GTEST_SKIP() << "The RKP VM (" << RKPVM_INSTANCE_NAME << ") is not present on this device.";
+    }
+    if (vendorApiLevel >= 202504) {
+        ASSERT_TRUE(AServiceManager_isDeclared(RKPVM_INSTANCE_NAME.c_str()));
+    }
+
+    auto rkpVmRpc = getHandle<IRemotelyProvisionedComponent>(RKPVM_INSTANCE_NAME);
+    ASSERT_NE(rkpVmRpc, nullptr) << "The RKP VM (" << RKPVM_INSTANCE_NAME
+                                 << ") RPC is unavailable.";
+
+    RpcHardwareInfo hardwareInfo;
+    auto status = rkpVmRpc->getHardwareInfo(&hardwareInfo);
+    if (!status.isOk()) {
+        GTEST_SKIP() << "The RKP VM is not supported on this system.";
+    }
+
+    bytevec rkpVmChallenge = randomBytes(MAX_CHALLENGE_SIZE);
+    bytevec rkpVmCsr;
+    auto rkpVmStatus =
+            rkpVmRpc->generateCertificateRequestV2({} /* keysToSign */, rkpVmChallenge, &rkpVmCsr);
+    ASSERT_TRUE(rkpVmStatus.isOk()) << rkpVmStatus.getDescription();
+
+    auto primaryKeyMintRpc = getHandle<IRemotelyProvisionedComponent>(DEFAULT_INSTANCE_NAME);
+    ASSERT_NE(primaryKeyMintRpc, nullptr)
+            << "The Primary KeyMint (" << DEFAULT_INSTANCE_NAME << ") RPC is unavailable.";
+
+    bytevec primaryKeyMintChallenge = randomBytes(MAX_CHALLENGE_SIZE);
+    bytevec primaryKeyMintCsr;
+    auto primaryKeyMintStatus = primaryKeyMintRpc->generateCertificateRequestV2(
+            {} /* keysToSign */, primaryKeyMintChallenge, &primaryKeyMintCsr);
+    ASSERT_TRUE(primaryKeyMintStatus.isOk()) << primaryKeyMintStatus.getDescription();
+
+    auto equal = compareRootPublicKeysInDiceChains(rkpVmCsr, RKPVM_INSTANCE_NAME, primaryKeyMintCsr,
+                                                   DEFAULT_INSTANCE_NAME);
+    ASSERT_TRUE(equal) << equal.message();
+    ASSERT_TRUE(*equal) << "Primary KeyMint and RKP VM RPCs have different UDS public keys";
+}
+
+/**
+ * Suppose that there is a StrongBox KeyMint instance on the device.
+ *
+ * Then, this test verifies that "keymint" is a substring of the component name in the configuration
+ * descriptor in the leaf certificate of the DICE chain for the primary ("default") KeyMint
+ * instance.
+ */
+// @VsrTest = 3.10-018.003
+TEST(NonParameterizedTests, componentNameInConfigurationDescriptorForPrimaryKeyMintInstance) {
+    int vendor_api_level = get_vendor_api_level();
+    if (vendor_api_level < 202504) {
+        GTEST_SKIP() << "Applies only to vendor API level >= 202504, but this device is: "
+                     << vendor_api_level;
     }
 
     if (!AServiceManager_isDeclared(KEYMINT_STRONGBOX_INSTANCE_NAME.c_str())) {
@@ -266,11 +339,58 @@
     auto status = rpc->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
     EXPECT_TRUE(status.isOk()) << status.getDescription();
 
-    auto result = isCsrWithProperDiceChain(csr);
+    auto result = verifyComponentNameInKeyMintDiceChain(csr);
     ASSERT_TRUE(result) << result.message();
     ASSERT_TRUE(*result);
 }
 
+/**
+ * Check that ro.boot.vbmeta.device_state is not "locked" or ro.boot.verifiedbootstate
+ * is not "green" if and only if the mode on at least one certificate in the DICE chain
+ * is non-normal.
+ */
+TEST(NonParameterizedTests, unlockedBootloaderStatesImpliesNonnormalRkpVmDiceChain) {
+    if (!AServiceManager_isDeclared(RKPVM_INSTANCE_NAME.c_str())) {
+        GTEST_SKIP() << "The RKP VM (" << RKPVM_INSTANCE_NAME << ") is not present on this device.";
+    }
+
+    auto rpc = getHandle<IRemotelyProvisionedComponent>(RKPVM_INSTANCE_NAME);
+    ASSERT_NE(rpc, nullptr) << "The RKP VM (" << RKPVM_INSTANCE_NAME << ") RPC is unavailable.";
+
+    RpcHardwareInfo hardwareInfo;
+    auto status = rpc->getHardwareInfo(&hardwareInfo);
+    if (!status.isOk()) {
+        GTEST_SKIP() << "The RKP VM is not supported on this system.";
+    }
+
+    auto challenge = randomBytes(MAX_CHALLENGE_SIZE);
+    bytevec csr;
+    auto rkpVmStatus = rpc->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
+    ASSERT_TRUE(rkpVmStatus.isOk()) << status.getDescription();
+
+    auto isProper = isCsrWithProperDiceChain(csr, RKPVM_INSTANCE_NAME);
+    ASSERT_TRUE(isProper) << isProper.message();
+    if (!*isProper) {
+        GTEST_SKIP() << "Skipping test: Only a proper DICE chain has a mode set.";
+    }
+
+    auto nonNormalMode = hasNonNormalModeInDiceChain(csr, RKPVM_INSTANCE_NAME);
+    ASSERT_TRUE(nonNormalMode) << nonNormalMode.message();
+
+    auto deviceState = ::android::base::GetProperty("ro.boot.vbmeta.device_state", "");
+    auto verifiedBootState = ::android::base::GetProperty("ro.boot.verifiedbootstate", "");
+
+    ASSERT_TRUE(!deviceState.empty());
+    ASSERT_TRUE(!verifiedBootState.empty());
+
+    ASSERT_EQ(deviceState != "locked" || verifiedBootState != "green", *nonNormalMode)
+            << "ro.boot.vbmeta.device_state = '" << deviceState
+            << "' and ro.boot.verifiedbootstate = '" << verifiedBootState << "', but the DICE "
+            << " chain has a " << (*nonNormalMode ? "non-normal" : "normal") << " DICE mode."
+            << " Locked devices must report normal, and unlocked devices must report "
+            << " non-normal.";
+}
+
 using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
 
 INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
@@ -344,9 +464,8 @@
  */
 TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
     // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
-    std::shared_ptr<IKeyMintDevice> keyMint;
-    if (!matching_keymint_device(GetParam(), &keyMint)) {
-        // No matching IKeyMintDevice.
+    auto keyMint = matchingKeyMintDevice(GetParam());
+    if (!keyMint) {
         GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
         return;
     }
@@ -424,6 +543,32 @@
     check_maced_pubkey(macedPubKey, testMode, nullptr);
 }
 
+/**
+ * Generate and validate at most 2**16 production-mode keys. This aims to catch issues that do not
+ * deterministically show up. In practice, this will test far fewer keys, but a certain number are
+ * tested at a minimum.
+ */
+TEST_P(GenerateKeyTests, generateManyEcdsaP256KeysInProdMode) {
+    const auto start = std::chrono::steady_clock::now();
+    const auto time_bound = std::chrono::seconds(5);
+    const auto upper_bound = 1 << 16;
+    const auto lower_bound = 1 << 8;
+    for (auto iteration = 0; iteration < upper_bound; iteration++) {
+        MacedPublicKey macedPubKey;
+        bytevec privateKeyBlob;
+        bool testMode = false;
+        auto status =
+                provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
+        ASSERT_TRUE(status.isOk());
+        vector<uint8_t> coseKeyData;
+        check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
+        const auto current_time = std::chrono::steady_clock::now() - start;
+        if (iteration >= lower_bound && current_time >= time_bound) {
+            break;
+        }
+    }
+}
+
 class CertificateRequestTestBase : public VtsRemotelyProvisionedComponentTests {
   protected:
     CertificateRequestTestBase()
@@ -490,9 +635,9 @@
                 &protectedData, &keysToSignMac);
         ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-        auto result = verifyProductionProtectedData(
-                deviceInfo, cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_,
-                rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+        auto result = verifyProductionProtectedData(deviceInfo, cppbor::Array(), keysToSignMac,
+                                                    protectedData, testEekChain_, eekId_,
+                                                    rpcHardwareInfo, GetParam(), challenge_);
         ASSERT_TRUE(result) << result.message();
     }
 }
@@ -515,9 +660,9 @@
             &protectedData, &keysToSignMac);
     ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-    auto firstBcc = verifyProductionProtectedData(
-            deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
-            eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+    auto firstBcc = verifyProductionProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(),
+                                                  keysToSignMac, protectedData, testEekChain_,
+                                                  eekId_, rpcHardwareInfo, GetParam(), challenge_);
     ASSERT_TRUE(firstBcc) << firstBcc.message();
 
     status = provisionable_->generateCertificateRequest(
@@ -525,9 +670,9 @@
             &protectedData, &keysToSignMac);
     ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-    auto secondBcc = verifyProductionProtectedData(
-            deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
-            eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+    auto secondBcc = verifyProductionProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(),
+                                                   keysToSignMac, protectedData, testEekChain_,
+                                                   eekId_, rpcHardwareInfo, GetParam(), challenge_);
     ASSERT_TRUE(secondBcc) << secondBcc.message();
 
     // Verify that none of the keys in the first BCC are repeated in the second one.
@@ -575,9 +720,9 @@
                 &keysToSignMac);
         ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-        auto result = verifyProductionProtectedData(
-                deviceInfo, cborKeysToSign_, keysToSignMac, protectedData, testEekChain_, eekId_,
-                rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+        auto result = verifyProductionProtectedData(deviceInfo, cborKeysToSign_, keysToSignMac,
+                                                    protectedData, testEekChain_, eekId_,
+                                                    rpcHardwareInfo, GetParam(), challenge_);
         ASSERT_TRUE(result) << result.message();
     }
 }
@@ -765,7 +910,8 @@
                 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
         ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-        auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge);
+        auto result = verifyProductionCsr(cppbor::Array(), csr, rpcHardwareInfo, GetParam(),
+                                          challenge, isRkpVmInstance_);
         ASSERT_TRUE(result) << result.message();
     }
 }
@@ -786,7 +932,8 @@
         auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge, &csr);
         ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-        auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge);
+        auto result = verifyProductionCsr(cborKeysToSign_, csr, rpcHardwareInfo, GetParam(),
+                                          challenge, isRkpVmInstance_);
         ASSERT_TRUE(result) << result.message();
     }
 }
@@ -816,13 +963,15 @@
     auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
     ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-    auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
+    auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, rpcHardwareInfo, GetParam(),
+                                        challenge_, isRkpVmInstance_);
     ASSERT_TRUE(firstCsr) << firstCsr.message();
 
     status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
     ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-    auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
+    auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, rpcHardwareInfo, GetParam(),
+                                         challenge_, isRkpVmInstance_);
     ASSERT_TRUE(secondCsr) << secondCsr.message();
 
     ASSERT_EQ(**firstCsr, **secondCsr);
@@ -840,7 +989,8 @@
     auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
     ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-    auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
+    auto result = verifyProductionCsr(cborKeysToSign_, csr, rpcHardwareInfo, GetParam(), challenge_,
+                                      isRkpVmInstance_);
     ASSERT_TRUE(result) << result.message();
 }
 
@@ -908,9 +1058,8 @@
 // @VsrTest = 3.10-015
 TEST_P(CertificateRequestV2Test, DeviceInfo) {
     // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
-    std::shared_ptr<IKeyMintDevice> keyMint;
-    if (!matching_keymint_device(GetParam(), &keyMint)) {
-        // No matching IKeyMintDevice.
+    std::shared_ptr<IKeyMintDevice> keyMint = matchingKeyMintDevice(GetParam());
+    if (!keyMint) {
         GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
         return;
     }
@@ -970,11 +1119,13 @@
             provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
     ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getDescription();
 
-    auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_);
+    auto result =
+            verifyProductionCsr(cppbor::Array(), csr, rpcHardwareInfo, GetParam(), challenge_);
     ASSERT_TRUE(result) << result.message();
 
     std::unique_ptr<cppbor::Array> csrPayload = std::move(*result);
     ASSERT_TRUE(csrPayload);
+    ASSERT_TRUE(csrPayload->size() > 2);
 
     auto deviceInfo = csrPayload->get(2)->asMap();
     ASSERT_TRUE(deviceInfo);
@@ -995,7 +1146,7 @@
     ASSERT_TRUE(bootPatchLevel);
     ASSERT_TRUE(securityLevel);
 
-    auto kmDeviceName = device_suffix(GetParam());
+    auto kmDeviceName = deviceSuffix(GetParam());
 
     // Compare DeviceInfo against IDs attested by KeyMint.
     ASSERT_TRUE((securityLevel->value() == "tee" && kmDeviceName == "default") ||
@@ -1020,10 +1171,10 @@
 TEST_P(VsrRequirementTest, VsrEnforcementTest) {
     RpcHardwareInfo hwInfo;
     ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
-    int vsr_api_level = get_vsr_api_level();
-    if (vsr_api_level < 34) {
-        GTEST_SKIP() << "Applies only to VSR API level 34 or newer, this device is: "
-                     << vsr_api_level;
+    int vendor_api_level = get_vendor_api_level();
+    if (vendor_api_level < __ANDROID_API_U__) {
+        GTEST_SKIP() << "Applies only to vendor API level >= 34, but this device is: "
+                     << vendor_api_level;
     }
     EXPECT_GE(hwInfo.versionNumber, 3)
             << "VSR 14+ requires IRemotelyProvisionedComponent v3 or newer.";
diff --git a/security/secretkeeper/aidl/Android.bp b/security/secretkeeper/aidl/Android.bp
index d282621..f0b7894 100644
--- a/security/secretkeeper/aidl/Android.bp
+++ b/security/secretkeeper/aidl/Android.bp
@@ -25,7 +25,7 @@
         "android.hardware.security.authgraph-V1",
     ],
     stability: "vintf",
-    frozen: true,
+    frozen: false,
     backend: {
         java: {
             enabled: true,
@@ -88,6 +88,6 @@
 rust_defaults {
     name: "secretkeeper_use_latest_hal_aidl_rust",
     rustlibs: [
-        "android.hardware.security.secretkeeper-V1-rust",
+        "android.hardware.security.secretkeeper-V2-rust",
     ],
 }
diff --git a/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl
index 8ce37cd..ed48480 100644
--- a/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl
+++ b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl
@@ -38,6 +38,7 @@
   byte[] processSecretManagementRequest(in byte[] request);
   void deleteIds(in android.hardware.security.secretkeeper.SecretId[] ids);
   void deleteAll();
+  android.hardware.security.secretkeeper.PublicKey getSecretkeeperIdentity();
   const int ERROR_UNKNOWN_KEY_ID = 1;
   const int ERROR_INTERNAL_ERROR = 2;
   const int ERROR_REQUEST_MALFORMED = 3;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/PublicKey.aidl
similarity index 89%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/PublicKey.aidl
index ca8b3eb..f690abf 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/PublicKey.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -31,8 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.security.secretkeeper;
+/* @hide */
+@VintfStability
+parcelable PublicKey {
+  byte[] keyMaterial;
 }
diff --git a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl
index b07dba8..91493a1 100644
--- a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl
+++ b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl
@@ -17,6 +17,7 @@
 package android.hardware.security.secretkeeper;
 
 import android.hardware.security.authgraph.IAuthGraphKeyExchange;
+import android.hardware.security.secretkeeper.PublicKey;
 import android.hardware.security.secretkeeper.SecretId;
 
 @VintfStability
@@ -101,4 +102,12 @@
      * Delete data of all clients.
      */
     void deleteAll();
+
+    /**
+     * Gets the public key of the secret keeper instance. This should be a CBOR-encoded
+     * COSE_Key, as a PubKeyEd25519 / PubKeyECDSA256 / PubKeyECDSA384, as defined in
+     * generateCertificateRequestV2.cddl. Clients must have a trusted way of ensuring
+     * this key is valid.
+     */
+    PublicKey getSecretkeeperIdentity();
 }
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/PublicKey.aidl
similarity index 69%
copy from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
copy to security/secretkeeper/aidl/android/hardware/security/secretkeeper/PublicKey.aidl
index 4298ba9..ccc89b3 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
+++ b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/PublicKey.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -13,13 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.hardware.security.see.hwcrypto.types;
 
-import android.hardware.security.see.hwcrypto.types.AesKey;
+package android.hardware.security.secretkeeper;
 
-/*
- * Type encapsulating a clear key.
+/**
+ * Contents of a pubkey.
+ * @hide
  */
-union ExplicitKeyMaterial {
-    AesKey aes;
+@VintfStability
+parcelable PublicKey {
+    /**
+     * CBOR-encoded COSE_Key
+     */
+    byte[] keyMaterial;
 }
diff --git a/security/secretkeeper/aidl/vts/Android.bp b/security/secretkeeper/aidl/vts/Android.bp
index be07a7b..c84afae 100644
--- a/security/secretkeeper/aidl/vts/Android.bp
+++ b/security/secretkeeper/aidl/vts/Android.bp
@@ -38,6 +38,7 @@
     srcs: ["secretkeeper_test_client.rs"],
     defaults: [
         "rdroidtest.defaults",
+        "secretkeeper_use_latest_hal_aidl_rust",
     ],
     test_suites: [
         "general-tests",
@@ -45,7 +46,6 @@
     ],
     test_config: "AndroidTest.xml",
     rustlibs: [
-        "android.hardware.security.secretkeeper-V1-rust",
         "libauthgraph_boringssl",
         "libauthgraph_core",
         "libauthgraph_wire",
@@ -66,9 +66,10 @@
 rust_binary {
     name: "secretkeeper_cli",
     srcs: ["secretkeeper_cli.rs"],
+    defaults: ["secretkeeper_use_latest_hal_aidl_rust"],
     lints: "android",
-    rlibs: [
-        "android.hardware.security.secretkeeper-V1-rust",
+    prefer_rlib: true,
+    rustlibs: [
         "libanyhow",
         "libauthgraph_boringssl",
         "libauthgraph_core",
diff --git a/security/secretkeeper/aidl/vts/dice_sample.rs b/security/secretkeeper/aidl/vts/dice_sample.rs
index 4ef396a..d6379e5 100644
--- a/security/secretkeeper/aidl/vts/dice_sample.rs
+++ b/security/secretkeeper/aidl/vts/dice_sample.rs
@@ -283,7 +283,7 @@
             SUBCOMPONENT_AUTHORITY_HASH => hex::decode("ed255ae9ea98826f3f3a966849f0aaaf356d140c766a869048016e0ba10141af039fec5c53658ddebdad9c2339587c5ef5487bde89237ca79802238d91aebba8").unwrap(),
         },
         {
-            SUBCOMPONENT_NAME => "apex:com.android.btservices",
+            SUBCOMPONENT_NAME => "apex:com.android.bt",
             SUBCOMPONENT_SECURITY_VERSION => 990090000,
             SUBCOMPONENT_CODE_HASH => hex::decode("d7aa86dfdf92e662d2210cd2b3ad4e4522c917e9e287268363aa90e20f9ae16c").unwrap(),
             SUBCOMPONENT_AUTHORITY_HASH => hex::decode("a0d577d4a56cfad09aaa7abcd2355cd78872df85672f2faf9ac2fdf15c06147394e704c7473f28bed737803581a3d097275cc26d8095a4a896ee76167f9ee40e").unwrap(),
diff --git a/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs b/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
index 449a99a..b944865 100644
--- a/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
+++ b/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
@@ -16,6 +16,7 @@
 
 use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::ISecretkeeper::ISecretkeeper;
 use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::SecretId::SecretId;
+use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::PublicKey::PublicKey;
 use authgraph_vts_test as ag_vts;
 use authgraph_boringssl as boring;
 use authgraph_core::key;
@@ -70,20 +71,32 @@
     0x06, 0xAC, 0x36, 0x8B, 0x3C, 0x95, 0x50, 0x16, 0x67, 0x71, 0x65, 0x26, 0xEB, 0xD0, 0xC3, 0x98,
 ]);
 
-// Android expects the public key of Secretkeeper instance to be present in the Linux device tree.
+// Android expects the public key of Secretkeeper instance to be available either
+// a) by being present in the Linux device tree (prior to version 2 of the secretkeeper HAL), or
+// b) via the `getSecretKeeperIdentity` operation from v2 onwards.
 // This allows clients to (cryptographically) verify that they are indeed talking to the real
 // secretkeeper.
 // Note that this is the identity of the `default` instance (and not `nonsecure`)!
-fn get_secretkeeper_identity() -> Option<CoseKey> {
-    let path = Path::new(SECRETKEEPER_KEY_HOST_DT);
-    if path.exists() {
-        let key = fs::read(path).unwrap();
-        let mut key = CoseKey::from_slice(&key).unwrap();
-        key.canonicalize(CborOrdering::Lexicographic);
-        Some(key)
+fn get_secretkeeper_identity(instance: &str) -> Option<CoseKey> {
+    let sk = get_connection(instance);
+    let key_material = if sk.getInterfaceVersion().expect("Error getting sk interface version") >= 2 {
+        let PublicKey { keyMaterial } = sk.getSecretkeeperIdentity().expect("Error calling getSecretkeeperIdentity");
+        Some(keyMaterial)
     } else {
-        None
-    }
+        let path = Path::new(SECRETKEEPER_KEY_HOST_DT);
+        if path.exists() {
+            let key_material = fs::read(path).unwrap();
+            Some(key_material)
+        } else {
+            None
+        }
+    };
+
+    key_material.map(|km| {
+        let mut cose_key = CoseKey::from_slice(&km).expect("Error deserializing CoseKey from key material");
+        cose_key.canonicalize(CborOrdering::Lexicographic);
+        cose_key
+    })
 }
 
 fn get_instances() -> Vec<(String, String)> {
@@ -760,12 +773,12 @@
 }
 
 // This test checks that the identity of Secretkeeper (in context of AuthGraph key exchange) is
-// same as the one advertized in Linux device tree. This is only expected from `default` instance.
+// same as the one either a) advertized in Linux device tree or b) retrieved from SK itself
+// from (HAL v2 onwards). This is only expected from `default` instance.
 #[rdroidtest(get_instances())]
-#[ignore_if(|p| p != "default")]
 fn secretkeeper_check_identity(instance: String) {
-    let sk_key = get_secretkeeper_identity()
-        .expect("Failed to extract identity of default instance from device tree");
+    let sk_key = get_secretkeeper_identity(&instance)
+        .expect("Failed to extract identity of default instance");
     // Create a session with this expected identity. This succeeds only if the identity used by
     // Secretkeeper is sk_key.
     let _ = SkClient::with_expected_sk_identity(&instance, sk_key).unwrap();
diff --git a/security/secretkeeper/default/Android.bp b/security/secretkeeper/default/Android.bp
index 799188f..134afc9 100644
--- a/security/secretkeeper/default/Android.bp
+++ b/security/secretkeeper/default/Android.bp
@@ -28,9 +28,9 @@
     vendor_available: true,
     defaults: [
         "authgraph_use_latest_hal_aidl_rust",
+        "secretkeeper_use_latest_hal_aidl_rust",
     ],
     rustlibs: [
-        "android.hardware.security.secretkeeper-V1-rust",
         "libauthgraph_boringssl",
         "libauthgraph_core",
         "libauthgraph_hal",
@@ -50,9 +50,9 @@
     prefer_rlib: true,
     defaults: [
         "authgraph_use_latest_hal_aidl_rust",
+        "secretkeeper_use_latest_hal_aidl_rust",
     ],
     rustlibs: [
-        "android.hardware.security.secretkeeper-V1-rust",
         "libandroid_logger",
         "libbinder_rs",
         "liblog_rust",
diff --git a/security/secretkeeper/default/secretkeeper.xml b/security/secretkeeper/default/secretkeeper.xml
index 40aebe0..699fff0 100644
--- a/security/secretkeeper/default/secretkeeper.xml
+++ b/security/secretkeeper/default/secretkeeper.xml
@@ -19,7 +19,7 @@
 
     <hal format="aidl">
         <name>android.hardware.security.secretkeeper</name>
-        <version>1</version>
+        <version>2</version>
         <interface>
             <name>ISecretkeeper</name>
             <instance>nonsecure</instance>
diff --git a/security/secureclock/aidl/Android.bp b/security/secureclock/aidl/Android.bp
index 853ad89..d7e7b43 100644
--- a/security/secureclock/aidl/Android.bp
+++ b/security/secureclock/aidl/Android.bp
@@ -10,6 +10,7 @@
 aidl_interface {
     name: "android.hardware.security.secureclock",
     vendor_available: true,
+    frozen: true,
     srcs: [
         "android/hardware/security/secureclock/*.aidl",
     ],
diff --git a/security/secureclock/aidl/vts/functional/Android.bp b/security/secureclock/aidl/vts/functional/Android.bp
index a34668b..4e54561 100644
--- a/security/secureclock/aidl/vts/functional/Android.bp
+++ b/security/secureclock/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/security/see/Android.bp b/security/see/Android.bp
new file mode 100644
index 0000000..ba873e0
--- /dev/null
+++ b/security/see/Android.bp
@@ -0,0 +1,5 @@
+dirgroup {
+    name: "trusty_dirgroup_hardware_interfaces_security_see",
+    dirs: ["."],
+    visibility: ["//trusty/vendor/google/aosp/scripts"],
+}
diff --git a/security/see/OWNERS b/security/see/OWNERS
new file mode 100644
index 0000000..d1a606f
--- /dev/null
+++ b/security/see/OWNERS
@@ -0,0 +1,5 @@
+# include OWNERS from the top level trusty repo
+include trusty:main:/OWNERS
+
+paulcrowley@google.com
+swillden@google.com
diff --git a/security/see/authmgr/aidl/Android.bp b/security/see/authmgr/aidl/Android.bp
new file mode 100644
index 0000000..a32d4e9
--- /dev/null
+++ b/security/see/authmgr/aidl/Android.bp
@@ -0,0 +1,57 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.security.see.authmgr",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/security/see/authmgr/*.aidl",
+    ],
+    stability: "vintf",
+    frozen: false,
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            enabled: true,
+        },
+        rust: {
+            enabled: true,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.virt",
+            ],
+        },
+    },
+}
+
+// A rust_defaults that includes the latest authmgr AIDL library.
+// Modules that depend on authmgr directly can include this rust_defaults to avoid
+// managing dependency versions explicitly.
+rust_defaults {
+    name: "authmgr_use_latest_hal_aidl_rust",
+    rustlibs: [
+        "android.hardware.security.see.authmgr-V1-rust",
+    ],
+}
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/DiceChainEntry.aidl
similarity index 87%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/DiceChainEntry.aidl
index ea3a173..b775f95 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/DiceChainEntry.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -31,9 +31,8 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.security.see.authmgr;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable DiceChainEntry {
+  byte[] diceChainEntry;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/DiceLeafArtifacts.aidl
similarity index 85%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/DiceLeafArtifacts.aidl
index c1dc51c..0f61900 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/DiceLeafArtifacts.aidl
@@ -31,10 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
-@VintfStability
-union AcquiredInfoAndVendorCode {
-  android.hardware.biometrics.fingerprint.AcquiredInfo acquiredInfo = android.hardware.biometrics.fingerprint.AcquiredInfo.UNKNOWN;
-  int vendorCode;
+package android.hardware.security.see.authmgr;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable DiceLeafArtifacts {
+  android.hardware.security.see.authmgr.DiceChainEntry diceLeaf;
+  android.hardware.security.see.authmgr.DicePolicy diceLeafPolicy;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/DicePolicy.aidl
similarity index 87%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/DicePolicy.aidl
index ea3a173..f434c3c 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/DicePolicy.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -31,9 +31,8 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.security.see.authmgr;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable DicePolicy {
+  byte[] dicePolicy;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/Error.aidl
similarity index 66%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/Error.aidl
index c1dc51c..9e6a501 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/Error.aidl
@@ -31,10 +31,24 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
-@VintfStability
-union AcquiredInfoAndVendorCode {
-  android.hardware.biometrics.fingerprint.AcquiredInfo acquiredInfo = android.hardware.biometrics.fingerprint.AcquiredInfo.UNKNOWN;
-  int vendorCode;
+package android.hardware.security.see.authmgr;
+@Backing(type="int") @VintfStability
+enum Error {
+  OK = 0,
+  AUTHENTICATION_ALREADY_STARTED = (-1) /* -1 */,
+  INSTANCE_ALREADY_AUTHENTICATED = (-2) /* -2 */,
+  INVALID_DICE_CERT_CHAIN = (-3) /* -3 */,
+  INVALID_DICE_LEAF = (-4) /* -4 */,
+  INVALID_DICE_POLICY = (-5) /* -5 */,
+  DICE_POLICY_MATCHING_FAILED = (-6) /* -6 */,
+  SIGNATURE_VERIFICATION_FAILED = (-7) /* -7 */,
+  CONNECTION_HANDOVER_FAILED = (-8) /* -8 */,
+  CONNECTION_NOT_AUTHENTICATED = (-9) /* -9 */,
+  NO_CONNECTION_TO_AUTHORIZE = (-10) /* -10 */,
+  INVALID_INSTANCE_IDENTIFIER = (-11) /* -11 */,
+  MEMORY_ALLOCATION_FAILED = (-12) /* -12 */,
+  INSTANCE_PENDING_DELETION = (-13) /* -13 */,
+  CLIENT_PENDING_DELETION = (-14) /* -14 */,
+  AUTHENTICATION_NOT_STARTED = (-15) /* -15 */,
+  INSTANCE_CONTEXT_CREATION_DENIED = (-16) /* -16 */,
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/ExplicitKeyDiceCertChain.aidl
similarity index 87%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/ExplicitKeyDiceCertChain.aidl
index ea3a173..18d90eb 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/ExplicitKeyDiceCertChain.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -31,9 +31,8 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+package android.hardware.security.see.authmgr;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable ExplicitKeyDiceCertChain {
+  byte[] diceCertChain;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/IAuthMgrAuthorization.aidl
similarity index 73%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/IAuthMgrAuthorization.aidl
index c1dc51c..a120b49 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/IAuthMgrAuthorization.aidl
@@ -31,10 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.security.see.authmgr;
 @VintfStability
-union AcquiredInfoAndVendorCode {
-  android.hardware.biometrics.fingerprint.AcquiredInfo acquiredInfo = android.hardware.biometrics.fingerprint.AcquiredInfo.UNKNOWN;
-  int vendorCode;
+interface IAuthMgrAuthorization {
+  byte[32] initAuthentication(in android.hardware.security.see.authmgr.ExplicitKeyDiceCertChain diceCertChain, in @nullable byte[] instanceIdentifier);
+  void completeAuthentication(in android.hardware.security.see.authmgr.SignedConnectionRequest signedConnectionRequest, in android.hardware.security.see.authmgr.DicePolicy dicePolicy);
+  void authorizeAndConnectClientToTrustedService(in byte[] clientID, String serviceName, in byte[32] token, in android.hardware.security.see.authmgr.DiceLeafArtifacts clientDiceArtifacts);
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/SignedConnectionRequest.aidl
similarity index 87%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
copy to security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/SignedConnectionRequest.aidl
index 173ac17..46d8373 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
+++ b/security/see/authmgr/aidl/aidl_api/android.hardware.security.see.authmgr/current/android/hardware/security/see/authmgr/SignedConnectionRequest.aidl
@@ -31,10 +31,8 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
-@VintfStability
-parcelable EnrollmentProgressStep {
-  int durationMs;
-  android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes;
+package android.hardware.security.see.authmgr;
+@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability
+parcelable SignedConnectionRequest {
+  byte[] signedConnectionRequest;
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/DiceChainEntry.aidl
similarity index 63%
copy from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to security/see/authmgr/aidl/android/hardware/security/see/authmgr/DiceChainEntry.aidl
index c7be950..3b4a35b 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/DiceChainEntry.aidl
@@ -14,22 +14,18 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
-
-import android.hardware.biometrics.fingerprint.AcquiredInfo;
+package android.hardware.security.see.authmgr;
 
 /**
- * @hide
+ * A CBOR encoded DICE certificate.
  */
 @VintfStability
-union AcquiredInfoAndVendorCode {
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable DiceChainEntry {
     /**
-     * Acquired info as specified in AcqauiredInfo.aidl
+     * Data is CBOR encoded according to the `DiceChainEntry` CDDL in
+     * hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/
+     * generateCertificateRequestV2.cddl
      */
-    AcquiredInfo acquiredInfo = AcquiredInfo.UNKNOWN;
-
-    /**
-     * Vendor specific code
-     */
-    int vendorCode;
+    byte[] diceChainEntry;
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/DiceLeafArtifacts.aidl
similarity index 61%
copy from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to security/see/authmgr/aidl/android/hardware/security/see/authmgr/DiceLeafArtifacts.aidl
index c7be950..333096f 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/DiceLeafArtifacts.aidl
@@ -14,22 +14,17 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
+package android.hardware.security.see.authmgr;
 
-import android.hardware.biometrics.fingerprint.AcquiredInfo;
+import android.hardware.security.see.authmgr.DiceChainEntry;
+import android.hardware.security.see.authmgr.DicePolicy;
 
 /**
- * @hide
+ * This contains the DICE certificate and the DICE policy created for the client by the AuthMgr FE.
  */
 @VintfStability
-union AcquiredInfoAndVendorCode {
-    /**
-     * Acquired info as specified in AcqauiredInfo.aidl
-     */
-    AcquiredInfo acquiredInfo = AcquiredInfo.UNKNOWN;
-
-    /**
-     * Vendor specific code
-     */
-    int vendorCode;
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable DiceLeafArtifacts {
+    DiceChainEntry diceLeaf;
+    DicePolicy diceLeafPolicy;
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/DicePolicy.aidl
similarity index 63%
copy from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to security/see/authmgr/aidl/android/hardware/security/see/authmgr/DicePolicy.aidl
index c7be950..4b55330 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/DicePolicy.aidl
@@ -14,22 +14,18 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
-
-import android.hardware.biometrics.fingerprint.AcquiredInfo;
+package android.hardware.security.see.authmgr;
 
 /**
- * @hide
+ * DICE policy - CBOR encoded according to DicePolicy.cddl.
  */
 @VintfStability
-union AcquiredInfoAndVendorCode {
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable DicePolicy {
     /**
-     * Acquired info as specified in AcqauiredInfo.aidl
+     * Data is CBOR encoded according to the `DicePolicy` CDDL in
+     * hardware/interfaces/security/authgraph/aidl/android/hardware/security/authgraph/
+     * DicePolicy.cddl
      */
-    AcquiredInfo acquiredInfo = AcquiredInfo.UNKNOWN;
-
-    /**
-     * Vendor specific code
-     */
-    int vendorCode;
+    byte[] dicePolicy;
 }
diff --git a/security/see/authmgr/aidl/android/hardware/security/see/authmgr/Error.aidl b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/Error.aidl
new file mode 100644
index 0000000..f7c3592
--- /dev/null
+++ b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/Error.aidl
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.see.authmgr;
+
+/**
+ * AuthMgr error codes. Aidl will return these error codes as service specific errors in
+ * EX_SERVICE_SPECIFIC.
+ */
+@VintfStability
+@Backing(type="int")
+enum Error {
+    /** Success */
+    OK = 0,
+
+    /** Duplicated attempt to start authentication from the same transport ID */
+    AUTHENTICATION_ALREADY_STARTED = -1,
+
+    /** Duplicated authenticated attempt with the same instance ID */
+    INSTANCE_ALREADY_AUTHENTICATED = -2,
+
+    /** Invalid DICE certificate chain of the AuthMgr FE */
+    INVALID_DICE_CERT_CHAIN = -3,
+
+    /** Invalid DICE leaf of the client */
+    INVALID_DICE_LEAF = -4,
+
+    /** Invalid DICE policy */
+    INVALID_DICE_POLICY = -5,
+
+    /** The DICE chain to policy matching failed */
+    DICE_POLICY_MATCHING_FAILED = -6,
+
+    /** Invalid signature */
+    SIGNATURE_VERIFICATION_FAILED = -7,
+
+    /** Failed to handover the connection to the trusted service */
+    CONNECTION_HANDOVER_FAILED = -8,
+
+    /**
+     * An authentication required request (e.g. phase 2) is invoked on a non-authenticated
+     * connection
+     */
+    CONNECTION_NOT_AUTHENTICATED = -9,
+
+    /** There is no pending connection with a matching token to authorize in phase 2 */
+    NO_CONNECTION_TO_AUTHORIZE = -10,
+
+    /** Invalid instance identifier */
+    INVALID_INSTANCE_IDENTIFIER = -11,
+
+    /** Failed to allocate memory */
+    MEMORY_ALLOCATION_FAILED = -12,
+
+    /** An instance which is pending deletion is trying to authenticate */
+    INSTANCE_PENDING_DELETION = -13,
+
+    /** A client which is pending deletion is trying to authorize */
+    CLIENT_PENDING_DELETION = -14,
+
+    /** Trying to complete authentication for an instance for which authentication is not started */
+    AUTHENTICATION_NOT_STARTED = -15,
+
+    /** Creation of the pVM instance's context in the secure storage is not allowed */
+    INSTANCE_CONTEXT_CREATION_DENIED = -16,
+}
diff --git a/security/see/authmgr/aidl/android/hardware/security/see/authmgr/ExplicitKeyDiceCertChain.aidl b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/ExplicitKeyDiceCertChain.aidl
new file mode 100644
index 0000000..de23530
--- /dev/null
+++ b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/ExplicitKeyDiceCertChain.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.see.authmgr;
+
+/**
+ * DICE certificate chain - CBOR encoded according to ExplicitKeyDiceCertChain.cddl.
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable ExplicitKeyDiceCertChain {
+    /**
+     * Data is CBOR encoded according to the `ExplicitKeyDiceCertChain` CDDL in
+     * hardware/interfaces/security/authgraph/aidl/android/hardware/security/authgraph/
+     * ExplicitKeyDiceCertChain.cddl
+     */
+    byte[] diceCertChain;
+}
diff --git a/security/see/authmgr/aidl/android/hardware/security/see/authmgr/IAuthMgrAuthorization.aidl b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/IAuthMgrAuthorization.aidl
new file mode 100644
index 0000000..43c3bde
--- /dev/null
+++ b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/IAuthMgrAuthorization.aidl
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.see.authmgr;
+
+import android.hardware.security.see.authmgr.DiceLeafArtifacts;
+import android.hardware.security.see.authmgr.DicePolicy;
+import android.hardware.security.see.authmgr.ExplicitKeyDiceCertChain;
+import android.hardware.security.see.authmgr.SignedConnectionRequest;
+
+/**
+ * This is the interface to be implemented by an AuthMgr backend component (AuthMgr BE), in order to
+ * allow the AuthMgr frontend component (AuthMgr FE) in a pVM instance to authenticate itself and
+ * to authorize one or more clients in the pVM instance, in order to let the clients access
+ * trusted services in the Trusted Execution Environment (TEE).
+ *
+ * The following assumptions must be true for the underlying IPC mechanism and the transport layer:
+ *     1. Both parties should be able to retrieve a non-spoofable identifier of the other party from
+ *        the transport layer (a.k.a transport ID or vM ID), which stays the same throughout a given
+ *        boot cycle of a pVM instance. This is important to prevent person-in-the-middle (PITM)
+ *        attacks and to authorize a new connection from a pVM instance based on an already
+ *        authenicated connection from the same pVM instance.
+ *
+ *     2. Each of AuthMgr FE and the AuthMgr BE should be able to hand over a connection that is
+ *        setup between them to another party so that such connection can be used for communication
+ *        between the two new parties subsequently. This is important to be able to handover an
+ *        authorized connection established between the AuthMgr FE and the AuthMgr BE to a client in
+ *        in a pVM instance and a trusted service in TEE respectively.
+ *
+ *     3. This API should be exposed over an IPC mechanism that supports statefull connections. This
+ *        is important for the AuthMgr FE to setup an authenicated connection once per boot cycle
+ *        and reuse it to authorize multiple client connections afterwards, if needed.
+ *
+ *      4. AuthMgr FE has a mechanism for discovering and establishing a connection to the trusted
+ *         AuthMgr BE. Based on this assumptionson, mutual authentication is not covered by this
+ *         API.
+ *
+ * The AuthMgr authorization protocol consists of two phases:
+ *     1. Phase 1 authenticates the AuthMgr FE to the AuthMgr BE via the first two methods of this
+ *        API: `initAuthentication` and `completeAuthentication`. At the end of the successful
+ *        excecution of phase 1, the AuthMgr FE and the AuthMgr BE have an authenticated connection
+ *        established between them. Phase 1 also enforces rollback protection on AuthMgr FE in
+ *        addition to authentication.
+ *
+ *        Authentication is performed by verifying the AuthMgr FE's signature on the challenge
+ *        issued by the AuthMgr BE. The public signing key of the AuthMgr FE is obtained from the
+ *        validated DICE certificate chain for verifying the signature. Rollback protection is
+ *        enforced by matching the DICE certificate chain against the stored DICE policy.
+ *        AuthMgr FE uses this authenticated connection throughout the boot cycle of the pVM to send
+ *        phase 2 requests to the AuthMgr BE. Therefore, phase 1 needs to be executed only once per
+ *        boot cycle of the pVM. AuthMgr BE should take measures to prevent any duplicate
+ *        authentication attempts from the same instance or from any impersonating instances.
+ *
+ *     2. Phase 2 authorizes a client in the pVM to access trusted service(s) in the TEE and
+ *        establishes a new connection between the client and the trusted service based on the trust
+ *        in the authenticated connection established in phase 1. The client and the trusted service
+ *        can communicate independently from the AuthMgr(s) after the successful execution of
+ *        phase 2 of the authorization protocol.
+ *
+ *        The AuthMgr FE first opens a new vsock connection to the AuthMgr BE and sends a one-time
+ *        token over that connection. The AuthMgr FE then invokes the third method of this API
+ *        (`authorizeAndConnectClientToTrustedService`) on the authenticated connection established
+ *        with the AuthMgr BE in phase 1. Rollback protection is enforced on the client by matching
+ *        the client's DICE certificate against the stored DICE policy. The new connection is
+ *        authorized by matching the token sent over the new connection and the token sent over the
+ *        authenicated connection.
+ *
+ * AuthMgr BE should make sure that "use-after-destroy" threats are prevented in the implementation
+ * of this authorization protocol. This means that even if a client/pVM instance is created with the
+ * same identifier(s) of a deleted client/pVM instance, the new client should not be able to access
+ * the deleted client's secrets/resources created in the trusted services. The following
+ * requirements should be addressed in order to ensure this:
+ * 1) Each client should be identified by a unique identifier at the AuthMgr BE. The uniqueness
+ *    should be guaranteed across factory resets.
+ * 2) The client's unique identifier should be used when constructing the file path to store the
+ *    client's context, including the client's DICE policy, in the AuthMgr BE's secure storage.
+ * 3) The client's unique identifier should be conveyed to the trusted service(s) that the client
+ *    accesses, when an authorized connection is setup between the client and the trusted service in
+ *    phase 2. The trusted service(s) should mix in this unique client identifier when providing the
+ *    critical services to the clients (e.g. deriving HW-backed keys by the HWCrypto service,
+ *    storing data by the SecureStorage service).
+ *
+ * An example approach to build a unique identifier for a client is as follows:
+ * The AuthMgr BE stores a `global sequence number` in the secure storage that does not get
+ * wiped upon factory reset. Everytime the AuthMgr BE sees a new instance or a client, it assigns
+ * the current `global sequence number` as the unique sequence number of the instance or the client
+ * and increments the `global sequence number`.
+ */
+@VintfStability
+interface IAuthMgrAuthorization {
+    /**
+     * AuthMgr FE initiates the challenge-response protocol with the AuthMgr BE in order to
+     * authenticate the AuthMgr FE to the AuthMgr BE. AuthMgr BE creates and returns a challenge
+     * (a cryptographic random of 32 bytes) to the AuthMgr FE.
+     *
+     * The AuthMgr BE extracts the instance identifier from the DICE certificate chain of the
+     * AuthMgr FE (given in the input: `diceCertChain`). If the instance identifier is not included
+     * in the DICE certificate chain, then it should be sent in the optional
+     * input: `instanceIdentifier`. The instance identifier is used by the AuthMgr BE in this step
+     * to detect and reject any duplicate authentication attempts.
+     * The instance identifier is used in step 2 to build the file path in the secure storage to
+     * store the instance's context.
+     *
+     * If authentication is already started (but not completed) from the same transport ID, return
+     * the error code `AUTHENTICATION_ALREADY_STARTED`.
+     *
+     * @param diceCertChain - DICE certificate chain of the AuthMgr FE.
+     *
+     * @param instanceIdentifier - optional parameter to send the instance identifier, if it is not
+     *                             included in the DICE certificate chain
+     *
+     * @return challenge to be included in the signed response sent by the AuthMgr FE in
+     *         `completeAuthentication`
+     *
+     * @throws ServiceSpecificException:
+     *         Error::INSTANCE_ALREADY_AUTHENTICATED - when a pVM instance with the same
+     *         `instanceIdentifier` or the same transport id has already been authenticated.
+     *         Error::AUTHENTICATION_ALREADY_STARTED - when a pVM instance with the same
+     *         the same transport id has already started authentication
+     */
+    byte[32] initAuthentication(in ExplicitKeyDiceCertChain diceCertChain,
+            in @nullable byte[] instanceIdentifier);
+
+    /**
+     * AuthMgr FE invokes this method to complete phase 1 of the authorization protocol. The AuthMgr
+     * BE verifies the signature in `signedConnectionRequest` with the public signing key of the
+     * AuthMgr FE obtained from the DICE certificate chain.
+     *
+     * As per the CDDL for `SignedConnectionRequest` in SignedConnectionRequest.cddl, the AuthMgr FE
+     * includes the challenge sent by the AuthMgr BE and the unique transport IDs of the AuthMgr FE
+     * and AuthMgr BE in the signed response. This is to prevent replay attacks in the presence of
+     * more than one AuthMgr BE, where one AuthMgr BE may impersonate a pVM instance/AuthMgr FE to
+     * another AuthMgr BE. Both transport IDs are included for completeness, although it is
+     * sufficient to include either of them for the purpose of preventing such attacks.
+     *
+     * AuthMgr BE validates the DICE certificate chain by verifying all the signatures in the chain
+     * and by checking wither the root public key is trusted.
+     *
+     * The AuthMgr BE matches the DICE certificate chain of the AuthMgr FE to the DICE policy given
+     * in the input: `dicePolicy`. If this is the first invocation of this method during the
+     * lifetime of the AuthMgr FE, the AuthMgr BE stores the DICE policy in the secure storage as
+     * part of the pVM instance's context, upon successful matching of DICE chain to the policy.
+     * The file path for the storage of the pVM context is constructed using the instance
+     * identifier. Note that the creation of a pVM instance's context in the secure storage is
+     * allowed only during the factory, for the first version of this API. In the future, we expect
+     * to allow the creation of a pVM instance's context in the secure storage even after the device
+     * leaves the factory, based on hard-coded DICE policies and/or via a separate
+     * `IAuthMgrInstanceContextMaintenance` API.
+     *
+     * In the subsequent invocations of this method, the AuthMgr BE matches the given DICE chain
+     * to the stored DICE policy in order to enforce rollback protection. If that succeeds and if
+     * the given DICE poliy is different from the stored DICE policy, the AuthMgr BE replaces the
+     * stored DICE policy with the given DICE policy.
+     *
+     * Upon successful execution of this method, the AuthMgr BE should store some state associated
+     * with the connection, in order to distinguish authenicated connections from any
+     * non-authenticated connections. The state associated with the connection may cache certain
+     * artifacts such as instance identifier, instance sequence number, transport ID, DICE chain
+     * and DICE policy of the AuthMgr FE, so that they can be reused when serving phase 2 requests.
+     * The requests for phase 2 of the authorization protocol are allowed only on authenticated
+     * connections.
+     *
+     * @param signedConnectionRequest - signature from AuthMgr FE (CBOR encoded according to
+     *                                  SignedConnectionRequest.cddl)
+     *
+     * @param dicePolicy - DICE policy of the AuthMgr FE
+     *
+     * @throws ServiceSpecificException:
+     *         Error::AUTHENTICATION_NOT_STARTED - when the authentication process has not been
+     *             started for the pVM instance.
+     *         Error::INSTANCE_ALREADY_AUTHENTICATED - when a pVM instance with the same
+     *         `instanceIdentifier` or the same transport id has already been authenticated.
+     *         Error::SIGNATURE_VERIFICATION_FAILED - when the signature verification fails.
+     *         Error::INVALID_DICE_CERT_CHAIN - when the DICE certificate chain validation fails.
+     *         Error::DICE_POLICY_MATCHING_FAILED - when the DICE certificate chain to DICE policy
+     *             matching fails for the pVM instance.
+     *         Error::INSTANCE_CONTEXT_CREATION_DENIED - when the creation of the pVM instances's
+     *             context in the AuthMgr BE is not allowed.
+     *         Error::INSTANCE_PENDING_DELETION - when a pVM that is being deleted is trying to
+     *             authenticate.
+     *
+     */
+    void completeAuthentication(
+            in SignedConnectionRequest signedConnectionRequest, in DicePolicy dicePolicy);
+
+    /**
+     * When the AuthMgr FE receives a request from a client to access a trusted service, the
+     * AuthMgr FE first creates a new (out-of-band) connection with the AuthMgr BE and sends a
+     * one-time cryptographic token of 32 bytes over that new connection.
+     *
+     * The AuthMgr FE then invokes this method on the authenticated connection established with the
+     * AuthMgr BE in phase 1. When this method is invoked, the AuthMgr BE checks whether the
+     * underlying connection of this method call is already authenticated.
+     *
+     * The AuthMgr FE acts as the DICE manager for all the clients in the pVM and generates the DICE
+     * leaf certificate and the DICE leaf policy for the client, which are sent in the input:
+     * `clientDiceArtifacts`.
+     *
+     * The AuthMgr BE matches the client's DICE leaf certificate to the client's DICE policy.
+     * If this is the first invocation of this method in the lifetime of the client, the AuthMgr BE
+     * stores the client's DICE policy in the secure storage as part of the client's context, upon
+     * successful matching of the DICE certificate to the policy. The file path for the storage of
+     * the client's context should be constructed using the unique id assigned to the pVM instance
+     * by the AuthMgr BE (e.g. instance sequence number)  and the client ID. There is no use
+     * case for deleting a client context or a pVM context created in the secure storage, for the
+     * first version of this API, outside of the factory reset. In the future, we expect to
+     * expose APIs for those tasks.
+     *
+     * In the subsequent invocations of this method, the AuthMgr BE matches the given DICE leaf
+     * certificate to the stored DICE policy in order to enforce rollback protection. If that
+     * succeeds and if the given DICE policy is different from the stored DICE policy, the AuthMgr
+     * BE replaces the stored DICE policy with the given DICE policy.
+     *
+     * If the same client requests multiple trusted services or connects to the same trusted service
+     * multiple times during the same boot cycle of the pVM instance, it is recommended to validate
+     * the client's DICE artifacts only once for a given client as an optimization.
+     *
+     * The AuthMgr BE keeps track of the aforementioned new connections that are pending
+     * authorization along with the tokens sent over them and the transport ID of the pVM instance
+     * which created those connections.
+     *
+     * The AuthMgr FE sends the same token that was sent over an aforementioned new connection
+     * in the input: `token` of this method call, in order to authorize the new connection, based on
+     * the trust in the authenticated connection established in phase 1.
+     *
+     * Once the validation of the client's DICE artifacts is completed, the AuthMgr BE retrieves the
+     * pending new connection to be authorized, which is associated with a token that matches the
+     * token sent in this method call and a transport ID that matches the transport ID associated
+     * with the connection underlying this method call.
+     *
+     * Next the AuthMgr BE connects to the trusted service requested by the client in order to
+     * handover the new authorized connection to the trusted service. Once the connection
+     * handover is successful, the AuthMgr BE returns OK to the AuthMgr FE. Then the AuthMgr FE
+     * returns to the client a handle to the new connection (created at the beginning of phase 2).
+     * At this point, an authorized connection is setup between the client and the trusted service,
+     * which they can use to communicate independently of the AuthMgr FE and the AuthMgr BE.
+     *
+     * @param clientID - the identifier of the client in the pVM instance, which is unique in the
+     *                   context of the pVM instance
+     *
+     * @param service name - the name of the trusted service requested by the client
+     *
+     * @param token - the one-time token used to authorize the new connection created between the
+     *                AuthMgr FE and the AuthMgr BE
+     *
+     * @param clientDiceArtifacts - DICE leaf certificate and the DICE leaf policy of the client
+     *
+     * @throws ServiceSpecificException:
+     *         Error::CONNECTION_NOT_AUTHENTICATED - when the underlying connection of this method
+     *             call is not authenticated.
+     *         Error::DICE_POLICY_MATCHING_FAILED - when the DICE certificate chain to DICE policy
+     *             matching fails for the client.
+     *         Error::NO_CONNECTION_TO_AUTHORIZE - when there is no pending new connection that
+     *             is associated with a token and a transport ID that matches those of this
+     *             method call.
+     *         Error::CONNECTION_HANDOVER_FAILED - when the hanover of the authorized connection to
+     *             the trusted service fails.
+     *         Error::CLIENT_PENDING_DELETION - when a client that is being deleted is trying to be
+     *             authorized.
+     */
+    void authorizeAndConnectClientToTrustedService(in byte[] clientID, String serviceName,
+            in byte[32] token, in DiceLeafArtifacts clientDiceArtifacts);
+}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/SignedConnectionRequest.aidl
similarity index 60%
copy from biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
copy to security/see/authmgr/aidl/android/hardware/security/see/authmgr/SignedConnectionRequest.aidl
index c7be950..f258603 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/SignedConnectionRequest.aidl
@@ -14,22 +14,16 @@
  * limitations under the License.
  */
 
-package android.hardware.biometrics.fingerprint;
-
-import android.hardware.biometrics.fingerprint.AcquiredInfo;
+package android.hardware.security.see.authmgr;
 
 /**
- * @hide
+ * The response from the AuthMgr FE which includes the challenge sent by the AuthMgr BE and other
+ * information signed by the AuthMgr FE's signing key.
  */
-@VintfStability
-union AcquiredInfoAndVendorCode {
-    /**
-     * Acquired info as specified in AcqauiredInfo.aidl
-     */
-    AcquiredInfo acquiredInfo = AcquiredInfo.UNKNOWN;
 
-    /**
-     * Vendor specific code
-     */
-    int vendorCode;
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true)
+parcelable SignedConnectionRequest {
+    /* Data is CBOR encoded according the CDDL in ./SignedConnectionRequest.cddl */
+    byte[] signedConnectionRequest;
 }
diff --git a/security/see/authmgr/aidl/android/hardware/security/see/authmgr/SignedConnectionRequest.cddl b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/SignedConnectionRequest.cddl
new file mode 100644
index 0000000..a74ccd7
--- /dev/null
+++ b/security/see/authmgr/aidl/android/hardware/security/see/authmgr/SignedConnectionRequest.cddl
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+SignedConnectionRequestProtected = {
+    1 : AlgorithmEdDSA / AlgorithmES256,
+}
+
+SignedConnectionRequest = [ ; COSE_Sign1 (untagged) [RFC9052 s4.2]
+    protected: bstr .cbor SignedConnectionRequesProtected,
+    unprotected: {},
+    payload: bstr .cbor ConnectionRequest,
+    signature: bstr     ; PureEd25519(privateKey, SignedResponseSigStruct) /
+                        ; ECDSA(privateKey, SignedResponseSigStruct)
+]
+
+ConnectionRequestSigStruct = [ ; Sig_structure for SignedConnectionRequest [ RFC9052 s4.4]
+    context: "Signature1",
+    body_protected: bstr .cbor SignedConnectionRequesProtected,
+    external_aad: bstr .cbor ExternalAADForDICESignedConnectionRequest,
+    payload: bstr .cbor ConnectionRequest,
+]
+
+; The payload structure signed by the DICE signing key
+ConnectionRequest [
+    challenge: bstr .size 32,
+    transport_type: TransportType,  ; this indicates what CBOR structure should be exected for the
+                                    ; next element (i.e. transport_id_info)
+    transport_id_info: TransportIdInfo, ; this information is used to detect person-in-the-middle
+                                        ; attacks
+]
+
+; The unique id assigned to the `ConnectionRequest` payload structure
+ConnectionRequestUuid = h'34c82916 9579 4d86 baef 592a066419e4' ; bstr .size 16 (UUID v4 - RFC 9562)
+
+; An integer that identifies the type of the transport used for communication between clients and
+; trusted services
+TransportType = &(
+    FFA: 1,
+    ; Any other transport type(s) also be defined here
+)
+
+; Identity information of the peers provided by the transport layer
+TransportIdInfo = &(
+    FFATransportId,
+    ; Any other type(s) containing transport layer identity information should also be defiend here
+)
+
+; Transport ids (a.k.a VM IDs) provided by the FFA transport
+FFATransportId = [
+    feID: uint .size 2, ; FF-A partition ID of the AuthMgr FE
+    beID: uint .size 2, ; FF-A partition ID of the AuthMgr BE
+]
+
+; External AAD to be added to any Sig_structure signed by the DICE signing key, with the mandatory
+; field of `uuid_of_payload_struct` of type UUID v4 (RFC 9562). This field is required to ensure
+; that both the signer and the verifier refer to the same payload structure, given that there are
+; various payload structures signed by the DICE signing key in different protocols in Android.
+ExternalAADForDICESigned = [
+    uuid_of_payload_struct: buuid,
+]
+
+; RFC8610 - Section 3.6
+buuid = #6.37(bstr .size 16)
+
+ExternalAADForDICESignedConnectionRequest = [ ; ExternalAADForDICESigned for ConnectionRequest
+    uuid_of_payload_struct: #6.37(ConnectionRequestUuid),
+]
+
+AlgorithmES256 = -7              ; [RFC9053 s2.1]
+AlgorithmEdDSA = -8              ; [RFC9053 s2.2]
diff --git a/security/see/authmgr/aidl/vts/Android.bp b/security/see/authmgr/aidl/vts/Android.bp
new file mode 100644
index 0000000..3d6fce2
--- /dev/null
+++ b/security/see/authmgr/aidl/vts/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["Android-Apache-2.0"],
+    default_team: "trendy_team_trusty",
+}
+
+rust_test {
+    name: "VtsAidlAuthMgrNonExistentTest",
+    srcs: ["test.rs"],
+    require_root: true,
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+    rustlibs: [
+        "libbinder_rs",
+    ],
+}
diff --git a/security/see/authmgr/aidl/vts/test.rs b/security/see/authmgr/aidl/vts/test.rs
new file mode 100644
index 0000000..45533a7
--- /dev/null
+++ b/security/see/authmgr/aidl/vts/test.rs
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+//! Test for asserting the non-existence of an IAuthMgrAuthorization.aidl
+
+#![cfg(test)]
+
+use binder;
+
+const AUTHMGR_INTERFACE_NAME: &str = "android.hardware.security.see.authmgr.IAuthMgrAuthorization";
+
+#[test]
+fn test_authmgr_non_existence() {
+    let authmgr_instances =  match binder::get_declared_instances(AUTHMGR_INTERFACE_NAME) {
+        Ok(vec) => vec,
+        Err(e) => {
+            panic!("failed to retrieve the declared interfaces for AuthMgr: {:?}", e);
+        }
+    };
+    assert!(authmgr_instances.is_empty());
+}
diff --git a/security/see/hdcp/README.md b/security/see/hdcp/README.md
new file mode 100644
index 0000000..76b8670
--- /dev/null
+++ b/security/see/hdcp/README.md
@@ -0,0 +1,65 @@
+# IHDCPAuthControl as a Trusted HAL service
+
+IHDCPAuthControl is expected to be a service implemented in a TEE.
+We provide a default reference implementation and its integration in Trusty
+as an example.
+
+The VTS test for a Trusted HAL service ought to run in the VM.
+We provide an integration of the VTS test in a Trusty VM,
+and later in a Microdroid VM (b/380632474).
+
+This interface shall not be exposed to the host and thus shall be part of
+the list of excluded interfaces from
+[compatibility_matrices/exclude/fcm_exclude.cpp](../../../compatibility_matrices/exclude/fcm_exclude.cpp)
+
+## 1. Mock Implementation
+
+The mock implementation under default/src/lib.rs is expected to be integrated in a
+TEE. For AOSP testing we offer two virtual device testing options:
+
+- Cuttlefish AVD, where the reference implementation is integrated in an AVF VM, emulating a TEE.
+- Trusty QEMU AVD, where the reference implementation is integrated in a Trusty TEE image (executed in secure world)
+
+### 1.1. Cuttlefish: Integrate in an AVF HAL pVM (Trusty)
+
+In Cuttlefish, we emulate a TEE with an AVF Trusty pVM.
+The VM2TZ IPC is emulated with a vsock port forward utility (b/379582767).
+
+Until vsock port forwarding is supported, the trusty_test_vm is used temporarily.
+(VTS tests and HAL implementation will be in same pVM).
+
+TODO: complete when trusty_hal_vm is created
+
+In order to add the mock HdcpAuthControlService to the trusty_test_vm, make sure
+that `hardware/interfaces/security/see/hdcp/default` is added to the
+trusty_test_vm makefile, by adding it to
+[trusty/device/x86/generic-x86_64/project/generic-x86_64-inc.mk](../../../../../trusty/device/x86/generic-x86_64/project/generic-x86_64-inc.mk)
+
+### 1.2. Trusty QEMU AVD: Integrate as a TA in Trusty TEE
+
+In order to add the mock HdcpAuthControlService to the Trusty TEE, make sure
+that `hardware/interfaces/security/see/hdcp/default` is added to
+[trusty/device/arm/generic-arm64/project/generic-arm-inc.mk](../../../../../trusty/device/arm/generic-arm64/project/generic-arm-inc.mk)
+
+
+## 2. VTS Tests
+
+IHdcpAuthControl service is expected to only be exposed to AVF pVM.
+
+The VTS tests shall verify:
+
+- IHdcpAuthControl cannot be accessed from the Android Host:
+
+   see [aidl/vts/src/host_test.rs](aidl/vts/host_test.rs)
+
+- IHdcpAuthControl can be accessed from an AVF pVM:
+
+   see [aidl/vts/src/vm_test.rs](aidl/vts/src/vm_test.rs)
+   see [aidl/vts/AndroidTest.xml](aidl/vts/AndroidTest.xml)
+
+
+To integrate the VTS test in the trusty_test_vm:
+
+1.
+1. add the test to [hardware/interfaces/security/see/usertests-rust-inc.mk](../usertests-rust-inc.mk)
+
diff --git a/security/see/hdcp/aidl/Android.bp b/security/see/hdcp/aidl/Android.bp
new file mode 100644
index 0000000..ad1db37
--- /dev/null
+++ b/security/see/hdcp/aidl/Android.bp
@@ -0,0 +1,57 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_team: "trendy_team_trusty",
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+aidl_interface {
+    name: "android.hardware.security.see.hdcp",
+    vendor_available: true,
+    srcs: ["android/hardware/security/see/hdcp/*.aidl"],
+    imports: [
+        "android.hardware.drm.common-V1",
+    ],
+    stability: "vintf",
+    frozen: false,
+    backend: {
+        java: {
+            enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+        ndk: {
+            min_sdk_version: "34",
+        },
+        rust: {
+            enabled: true,
+            gen_mockall: true,
+            additional_rustlibs: [
+                "libmockall",
+            ],
+        },
+    },
+}
+
+// A rust_defaults that includes the latest hdcp AIDL library.
+// Modules that depend on hdcp directly can include this rust_defaults to avoid
+// managing dependency versions explicitly.
+rust_defaults {
+    name: "hdcp_use_latest_hal_aidl_rust",
+    rustlibs: [
+        "android.hardware.security.see.hdcp-V1-rust",
+    ],
+}
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/hdcp/aidl/aidl_api/android.hardware.security.see.hdcp/current/android/hardware/security/see/hdcp/IHdcpAuthControl.aidl
similarity index 64%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
copy to security/see/hdcp/aidl/aidl_api/android.hardware.security.see.hdcp/current/android/hardware/security/see/hdcp/IHdcpAuthControl.aidl
index 5c26cc2..b73d554 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/hdcp/aidl/aidl_api/android.hardware.security.see.hdcp/current/android/hardware/security/see/hdcp/IHdcpAuthControl.aidl
@@ -31,7 +31,28 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-interface IHwCryptoOperations {
-  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+package android.hardware.security.see.hdcp;
+@VintfStability
+interface IHdcpAuthControl {
+  android.hardware.drm.HdcpLevels getHdcpLevels();
+  void trySetHdcpLevel(in android.hardware.drm.HdcpLevel level);
+  android.hardware.security.see.hdcp.IHdcpAuthControl.PendingHdcpLevelResult getPendingHdcpLevel();
+  parcelable HalErrorCode {
+    const int NO_ERROR = 0;
+    const int GENERIC_ERROR = (-1) /* -1 */;
+    const int BAD_STATE = (-2) /* -2 */;
+    const int UNSUPPORTED = (-3) /* -3 */;
+    const int SERIALIZATION_ERROR = (-4) /* -4 */;
+    const int ALLOCATION_ERROR = (-5) /* -5 */;
+    const int BAD_PARAMETER = (-7) /* -7 */;
+    const int UNAUTHORIZED = (-8) /* -8 */;
+  }
+  parcelable PendingHdcpLevelResult {
+    android.hardware.security.see.hdcp.IHdcpAuthControl.PendingHdcpLevelResult.Status status;
+    android.hardware.drm.HdcpLevel level;
+    enum Status {
+      NONE,
+      PENDING,
+    }
+  }
 }
diff --git a/security/see/hdcp/aidl/android/hardware/security/see/hdcp/IHdcpAuthControl.aidl b/security/see/hdcp/aidl/android/hardware/security/see/hdcp/IHdcpAuthControl.aidl
new file mode 100644
index 0000000..b9a1fe5
--- /dev/null
+++ b/security/see/hdcp/aidl/android/hardware/security/see/hdcp/IHdcpAuthControl.aidl
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.security.see.hdcp;
+
+/**
+ * IHdcpAuthControl is used by the OEMCrypto Trusted Application to interact
+ * with a HDCP Encryption Trusted Application in order to control the
+ * HDCP Authentication Levels.
+ */
+@VintfStability
+interface IHdcpAuthControl {
+    /*
+     * Service error codes. Will be returned as service specific errors.
+     */
+    parcelable HalErrorCode {
+        /* Success */
+        const int NO_ERROR = 0;
+
+        /* Generic error */
+        const int GENERIC_ERROR = -1;
+
+        /* Desired operation cannot be performed because of the server current state */
+        const int BAD_STATE = -2;
+
+        /* Operation or parameters are not supported by the server */
+        const int UNSUPPORTED = -3;
+
+        /* Error encountered when parsing parameters */
+        const int SERIALIZATION_ERROR = -4;
+
+        /* Server ran out of memory when performing operation */
+        const int ALLOCATION_ERROR = -5;
+
+        /* Bad parameter supplied for the desired operation */
+        const int BAD_PARAMETER = -7;
+
+        /* Caller is not authorized to make this call */
+        const int UNAUTHORIZED = -8;
+    }
+    /**
+     * Result returned from the getPendingHdcpLevelResult API.
+     */
+    parcelable PendingHdcpLevelResult {
+        enum Status {
+            /**
+             * No pending HdcpLevel request
+             */
+            NONE,
+            /**
+             * a HdcpLevel request is pending, its level is provided in the
+             * |level| attribute
+             */
+            PENDING,
+        }
+        Status status;
+        android.hardware.drm.HdcpLevel level;
+    }
+
+    /**
+     * Return the currently negotiated and max supported HDCP levels.
+     *
+     * The current level is based on the display(s) the device is connected to.
+     * If multiple HDCP-capable displays are simultaneously connected to
+     * separate interfaces, this method returns the lowest negotiated HDCP level
+     * of all interfaces.
+     *
+     * The maximum HDCP level is the highest level that can potentially be
+     * negotiated. It is a constant for any device, i.e. it does not depend on
+     * downstream receiving devices that could be connected. For example, if
+     * the device has HDCP 1.x keys and is capable of negotiating HDCP 1.x, but
+     * does not have HDCP 2.x keys, then the maximum HDCP capability would be
+     * reported as 1.x. If multiple HDCP-capable interfaces are present, it
+     * indicates the highest of the maximum HDCP levels of all interfaces.
+     *
+     * This method should only be used for informational purposes, not for
+     * enforcing compliance with HDCP requirements. Trusted enforcement of HDCP
+     * policies must be handled by the DRM system.
+     *
+     * @return HdcpLevels parcelable
+     */
+    android.hardware.drm.HdcpLevels getHdcpLevels();
+
+    /**
+     * Attempts to set the device's HDCP auth level to |level|.
+     *
+     * @param level: desired HDCP level
+     *
+     * @return:
+     *     a service specific error based on <code>HalErrorCode</code>,
+     *     specifically:
+     *       + BAD_PARAMETER: when HDCP_UNKNOWN is requested
+     *       + UNSUPPORTED: when |level| is greater than the MaxLevel supported
+     *       + BAD_STATE: when the HDCP's service currentLevel is HDCP_NO_OUTPUT
+     *
+     */
+    void trySetHdcpLevel(in android.hardware.drm.HdcpLevel level);
+
+    /**
+     * Retrieve the pending level currently being processed by the HDCP service.
+     * The pending HDCP protection level might be higher than the level initially
+     * requested. This can occur when multiple applications or services are
+     * using HDCP concurrently, and a higher level is needed to satisfy
+     * all requirements.
+     *
+     * @return:
+     *      PendingHdcpLevelResult on success, which contains a status
+     *      and an optional level; on error a service specific error based on
+     *      <code>HalErrorCode</code> otherwise.
+     *
+     */
+    PendingHdcpLevelResult getPendingHdcpLevel();
+}
diff --git a/security/see/hdcp/aidl/trusty/drm/rust/rules.mk b/security/see/hdcp/aidl/trusty/drm/rust/rules.mk
new file mode 100644
index 0000000..742b6ab
--- /dev/null
+++ b/security/see/hdcp/aidl/trusty/drm/rust/rules.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2024 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.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+AIDL_DIR := hardware/interfaces/drm/aidl
+
+MODULE_AIDL_FLAGS := \
+	--stability=vintf \
+	--version=1 \
+
+MODULE_CRATE_NAME := android_hardware_drm
+
+MODULE_AIDL_LANGUAGE := rust
+
+MODULE_AIDL_PACKAGE := android/hardware/drm
+
+MODULE_AIDL_INCLUDES := \
+	-I $(AIDL_DIR) \
+
+MODULE_AIDLS := \
+    $(AIDL_DIR)/$(MODULE_AIDL_PACKAGE)/HdcpLevel.aidl   \
+    $(AIDL_DIR)/$(MODULE_AIDL_PACKAGE)/HdcpLevels.aidl   \
+
+include make/aidl.mk
diff --git a/security/see/hdcp/aidl/trusty/hdcp/rust/rules.mk b/security/see/hdcp/aidl/trusty/hdcp/rust/rules.mk
new file mode 100644
index 0000000..beab655
--- /dev/null
+++ b/security/see/hdcp/aidl/trusty/hdcp/rust/rules.mk
@@ -0,0 +1,47 @@
+# Copyright (C) 2024 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.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+AIDL_DIR := hardware/interfaces/security/see/hdcp/aidl
+DRM_AIDL_DIR := hardware/interfaces/drm/aidl
+
+MODULE_AIDL_FLAGS := \
+	--mockall \
+	--version=1 \
+
+MODULE_CRATE_NAME := android_hardware_security_see_hdcp
+
+MODULE_AIDL_LANGUAGE := rust
+
+MODULE_AIDL_PACKAGE := android/hardware/security/see/hdcp
+
+MODULE_AIDL_INCLUDES := \
+	-I $(AIDL_DIR) \
+	-I $(DRM_AIDL_DIR) \
+
+MODULE_AIDLS := \
+    $(AIDL_DIR)/$(MODULE_AIDL_PACKAGE)/IHdcpAuthControl.aidl   \
+
+MODULE_AIDL_RUST_DEPS := \
+	android_hardware_drm
+
+MODULE_LIBRARY_DEPS := \
+	hardware/interfaces/security/see/hdcp/aidl/trusty/drm/rust \
+	$(call FIND_CRATE,mockall) \
+
+include make/aidl.mk
diff --git a/security/see/hdcp/aidl/vts/Android.bp b/security/see/hdcp/aidl/vts/Android.bp
new file mode 100644
index 0000000..eadb9cd
--- /dev/null
+++ b/security/see/hdcp/aidl/vts/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["Android-Apache-2.0"],
+    default_team: "trendy_team_trusty",
+}
+
+rust_test {
+    name: "VtsAidlHdcpNonExistentTest",
+    srcs: ["src/host_test.rs"],
+    require_root: true,
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+    rustlibs: [
+        "libbinder_rs",
+    ],
+}
diff --git a/security/see/hdcp/aidl/vts/src/host_test.rs b/security/see/hdcp/aidl/vts/src/host_test.rs
new file mode 100644
index 0000000..f64de20
--- /dev/null
+++ b/security/see/hdcp/aidl/vts/src/host_test.rs
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+//! Test for asserting the non-existence of an IHdcpAuthControl.aidl
+
+#![cfg(test)]
+
+use binder;
+
+const HDCP_INTERFACE_NAME: &str = "android.hardware.security.see.hdcp.IHdcpAuthControl";
+
+#[test]
+fn test_hdcp_auth_control_non_existence() {
+    let hdcp_instances =  match binder::get_declared_instances(HDCP_INTERFACE_NAME) {
+        Ok(vec) => vec,
+        Err(e) => {
+            panic!("failed to retrieve the declared interfaces for HdcpAuthControl: {:?}", e);
+        }
+    };
+    assert!(hdcp_instances.is_empty());
+}
diff --git a/staging/security/see/hwcrypto/aidl/Android.bp b/security/see/hwcrypto/aidl/Android.bp
similarity index 76%
rename from staging/security/see/hwcrypto/aidl/Android.bp
rename to security/see/hwcrypto/aidl/Android.bp
index 3e7ee9e..e15f494 100644
--- a/staging/security/see/hwcrypto/aidl/Android.bp
+++ b/security/see/hwcrypto/aidl/Android.bp
@@ -8,8 +8,8 @@
 }
 
 aidl_interface {
-    name: "android.hardware.security.see",
-    unstable: false,
+    name: "android.hardware.security.see.hwcrypto",
+    stability: "vintf",
     host_supported: true,
     srcs: [
         "android/hardware/security/see/hwcrypto/*.aidl",
@@ -20,10 +20,15 @@
             enabled: false,
         },
         cpp: {
-            enabled: false,
+            enabled: true,
         },
         rust: {
             enabled: true,
         },
+        ndk: {
+            enabled: true,
+        },
     },
+    frozen: false,
+    system_ext_specific: true,
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/CryptoOperation.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/CryptoOperation.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/CryptoOperation.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/CryptoOperation.aidl
index 0a7e7a2..fd2904b 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/CryptoOperation.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/CryptoOperation.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto;
+@VintfStability
 union CryptoOperation {
   android.hardware.security.see.hwcrypto.MemoryBufferParameter setMemoryBuffer;
   android.hardware.security.see.hwcrypto.OperationParameters setOperationParameters;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/CryptoOperationErrorAdditionalInfo.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/CryptoOperationErrorAdditionalInfo.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/CryptoOperationErrorAdditionalInfo.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/CryptoOperationErrorAdditionalInfo.aidl
index 05780e1..66bed55 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/CryptoOperationErrorAdditionalInfo.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/CryptoOperationErrorAdditionalInfo.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto;
+@VintfStability
 parcelable CryptoOperationErrorAdditionalInfo {
   long failingCommandIndex;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/CryptoOperationResult.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/CryptoOperationResult.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/CryptoOperationResult.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/CryptoOperationResult.aidl
index 1088e27..7996b9a 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/CryptoOperationResult.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/CryptoOperationResult.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto;
+@VintfStability
 parcelable CryptoOperationResult {
   @nullable android.hardware.security.see.hwcrypto.ICryptoOperationContext context;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/CryptoOperationSet.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/CryptoOperationSet.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/CryptoOperationSet.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/CryptoOperationSet.aidl
index f3b9b43..75bb0dc 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/CryptoOperationSet.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/CryptoOperationSet.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto;
+@VintfStability
 parcelable CryptoOperationSet {
   @nullable android.hardware.security.see.hwcrypto.ICryptoOperationContext context;
   android.hardware.security.see.hwcrypto.CryptoOperation[] operations;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/ICryptoOperationContext.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/ICryptoOperationContext.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/ICryptoOperationContext.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/ICryptoOperationContext.aidl
index 472215f..7646656 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/ICryptoOperationContext.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/ICryptoOperationContext.aidl
@@ -32,5 +32,6 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto;
+@VintfStability
 interface ICryptoOperationContext {
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
similarity index 89%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
index 3763f0a..99eb761 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
@@ -32,15 +32,21 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto;
+@VintfStability
 interface IHwCryptoKey {
   android.hardware.security.see.hwcrypto.IHwCryptoKey.DiceCurrentBoundKeyResult deriveCurrentDicePolicyBoundKey(in android.hardware.security.see.hwcrypto.IHwCryptoKey.DiceBoundDerivationKey derivationKey);
   android.hardware.security.see.hwcrypto.IHwCryptoKey.DiceBoundKeyResult deriveDicePolicyBoundKey(in android.hardware.security.see.hwcrypto.IHwCryptoKey.DiceBoundDerivationKey derivationKey, in byte[] dicePolicyForKeyVersion);
   android.hardware.security.see.hwcrypto.IHwCryptoKey.DerivedKey deriveKey(in android.hardware.security.see.hwcrypto.IHwCryptoKey.DerivedKeyParameters parameters);
   android.hardware.security.see.hwcrypto.IHwCryptoOperations getHwCryptoOperations();
   android.hardware.security.see.hwcrypto.IOpaqueKey importClearKey(in android.hardware.security.see.hwcrypto.types.ExplicitKeyMaterial keyMaterial, in android.hardware.security.see.hwcrypto.KeyPolicy newKeyPolicy);
+  byte[] getCurrentDicePolicy();
+  android.hardware.security.see.hwcrypto.IOpaqueKey keyTokenImport(in android.hardware.security.see.hwcrypto.types.OpaqueKeyToken requestedKey, in byte[] sealingDicePolicy);
+  android.hardware.security.see.hwcrypto.IOpaqueKey getKeyslotData(android.hardware.security.see.hwcrypto.IHwCryptoKey.KeySlot slotId);
   enum DeviceKeyId {
     DEVICE_BOUND_KEY,
-    BATCH_KEY,
+  }
+  enum KeySlot {
+    KEYMINT_SHARED_HMAC_KEY,
   }
   union DiceBoundDerivationKey {
     android.hardware.security.see.hwcrypto.IOpaqueKey opaqueKey;
@@ -58,7 +64,7 @@
     int keySizeBytes;
   }
   union DerivedKeyPolicy {
-    android.hardware.security.see.hwcrypto.IHwCryptoKey.ClearKeyPolicy clearKey;
+    android.hardware.security.see.hwcrypto.IHwCryptoKey.ClearKeyPolicy clearKeyPolicy;
     byte[] opaqueKey;
   }
   parcelable DerivedKeyParameters {
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
similarity index 93%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
index 5c26cc2..3adb2f9 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto;
+@VintfStability
 interface IHwCryptoOperations {
-  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations);
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IOpaqueKey.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IOpaqueKey.aidl
similarity index 86%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IOpaqueKey.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IOpaqueKey.aidl
index 9cbf272..1121f01 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IOpaqueKey.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IOpaqueKey.aidl
@@ -32,8 +32,11 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto;
+@VintfStability
 interface IOpaqueKey {
   byte[] exportWrappedKey(in android.hardware.security.see.hwcrypto.IOpaqueKey wrappingKey);
   android.hardware.security.see.hwcrypto.KeyPolicy getKeyPolicy();
   byte[] getPublicKey();
+  android.hardware.security.see.hwcrypto.types.OpaqueKeyToken getShareableToken(in byte[] sealingDicePolicy);
+  void setProtectionId(in android.hardware.security.see.hwcrypto.types.ProtectionId protectionId, in android.hardware.security.see.hwcrypto.types.OperationType[] allowedOperations);
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/KeyPolicy.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/KeyPolicy.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/KeyPolicy.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/KeyPolicy.aidl
index 0e3896e..ca114c3 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/KeyPolicy.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/KeyPolicy.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto;
+@VintfStability
 parcelable KeyPolicy {
   android.hardware.security.see.hwcrypto.types.KeyUse usage;
   android.hardware.security.see.hwcrypto.types.KeyLifetime keyLifetime = android.hardware.security.see.hwcrypto.types.KeyLifetime.EPHEMERAL;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
index d88d5c8..1c49297 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto;
+@VintfStability
 parcelable MemoryBufferParameter {
   android.hardware.security.see.hwcrypto.MemoryBufferParameter.MemoryBuffer bufferHandle;
   int sizeBytes;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/OperationParameters.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/OperationParameters.aidl
similarity index 95%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/OperationParameters.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/OperationParameters.aidl
index 017e51c..d6f57ab 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/OperationParameters.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/OperationParameters.aidl
@@ -32,7 +32,9 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto;
+@VintfStability
 union OperationParameters {
   android.hardware.security.see.hwcrypto.types.SymmetricAuthOperationParameters symmetricAuthCrypto;
   android.hardware.security.see.hwcrypto.types.SymmetricOperationParameters symmetricCrypto;
+  android.hardware.security.see.hwcrypto.types.HmacOperationParameters hmac;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/PatternParameters.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/PatternParameters.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/PatternParameters.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/PatternParameters.aidl
index 0fd1ee7..7b9924e 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/PatternParameters.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/PatternParameters.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto;
+@VintfStability
 parcelable PatternParameters {
   long numberBlocksProcess;
   long numberBlocksCopy;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/AesCipherMode.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/AesCipherMode.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/AesCipherMode.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/AesCipherMode.aidl
index e7501ff..6ad2c09 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/AesCipherMode.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/AesCipherMode.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 union AesCipherMode {
   android.hardware.security.see.hwcrypto.types.CipherModeParameters cbc;
   android.hardware.security.see.hwcrypto.types.CipherModeParameters ctr;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl
index 4084abb..68ad142 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 union AesGcmMode {
   android.hardware.security.see.hwcrypto.types.AesGcmMode.AesGcmModeParameters gcmTag16;
   parcelable AesGcmModeParameters {
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/AesKey.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/AesKey.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/AesKey.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/AesKey.aidl
index f4bf786..78b1ff8 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/AesKey.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/AesKey.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 union AesKey {
   byte[16] aes128 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
   byte[32] aes256;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl
index 7a77521..83713ff 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 parcelable CipherModeParameters {
   byte[16] nonce;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
similarity index 95%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
index 933fb67..45cb234 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
@@ -32,6 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 union ExplicitKeyMaterial {
   android.hardware.security.see.hwcrypto.types.AesKey aes;
+  android.hardware.security.see.hwcrypto.types.HmacKey hmac;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/HalErrorCode.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/HalErrorCode.aidl
similarity index 96%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/HalErrorCode.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/HalErrorCode.aidl
index cd8b3c6..969e9c8 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/HalErrorCode.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/HalErrorCode.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 parcelable HalErrorCode {
   const int NO_ERROR = 0;
   const int GENERIC_ERROR = (-1) /* -1 */;
@@ -41,4 +42,5 @@
   const int ALLOCATION_ERROR = (-5) /* -5 */;
   const int INVALID_KEY = (-6) /* -6 */;
   const int BAD_PARAMETER = (-7) /* -7 */;
+  const int UNAUTHORIZED = (-8) /* -8 */;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/HmacKey.aidl
similarity index 90%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/HmacKey.aidl
index ea3a173..4d4e65d 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/HmacKey.aidl
@@ -32,8 +32,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+@VintfStability
+union HmacKey {
+  byte[32] sha256 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+  byte[64] sha512;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/HmacOperationParameters.aidl
similarity index 93%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
copy to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/HmacOperationParameters.aidl
index ea3a173..33a518d 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/HmacOperationParameters.aidl
@@ -32,8 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
-enum KeyPermissions {
-  ALLOW_EPHEMERAL_KEY_WRAPPING,
-  ALLOW_HARDWARE_KEY_WRAPPING,
-  ALLOW_PORTABLE_KEY_WRAPPING,
+@VintfStability
+parcelable HmacOperationParameters {
+  android.hardware.security.see.hwcrypto.IOpaqueKey key;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyLifetime.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/KeyLifetime.aidl
similarity index 97%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyLifetime.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/KeyLifetime.aidl
index db5964c..ddee337 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyLifetime.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/KeyLifetime.aidl
@@ -32,7 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
-@Backing(type="byte")
+@Backing(type="byte") @VintfStability
 enum KeyLifetime {
   EPHEMERAL,
   HARDWARE,
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
index ea3a173..919be32 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 enum KeyPermissions {
   ALLOW_EPHEMERAL_KEY_WRAPPING,
   ALLOW_HARDWARE_KEY_WRAPPING,
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyType.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/KeyType.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyType.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/KeyType.aidl
index 59b83c4..07a7ce4 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyType.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/KeyType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 enum KeyType {
   AES_128_CBC_NO_PADDING,
   AES_128_CBC_PKCS7_PADDING,
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyUse.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/KeyUse.aidl
similarity index 97%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyUse.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/KeyUse.aidl
index e888bdf..b607fd5 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/KeyUse.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/KeyUse.aidl
@@ -32,7 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
-@Backing(type="int")
+@Backing(type="int") @VintfStability
 enum KeyUse {
   ENCRYPT = 1,
   DECRYPT = 2,
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/MemoryBufferReference.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/MemoryBufferReference.aidl
similarity index 96%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/MemoryBufferReference.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/MemoryBufferReference.aidl
index 59c8757..184e21f 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/MemoryBufferReference.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/MemoryBufferReference.aidl
@@ -32,7 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
-@RustDerive(Clone=true, Copy=true)
+@RustDerive(Clone=true, Copy=true) @VintfStability
 parcelable MemoryBufferReference {
   int startOffset;
   int sizeBytes;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/OpaqueKeyToken.aidl
similarity index 95%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/OpaqueKeyToken.aidl
index ca8b3eb..6dfefcb 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/OpaqueKeyToken.aidl
@@ -32,7 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+@VintfStability
+parcelable OpaqueKeyToken {
+  byte[] keyToken;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationData.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/OperationData.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationData.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/OperationData.aidl
index aad3ac1..858ef1c 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationData.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/OperationData.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 union OperationData {
   android.hardware.security.see.hwcrypto.types.MemoryBufferReference memoryBufferReference;
   byte[] dataBuffer;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
index ca8b3eb..03c2bba 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 enum OperationType {
   READ,
   WRITE,
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/ProtectionId.aidl
similarity index 95%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/ProtectionId.aidl
index ca8b3eb..cb963ee 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/ProtectionId.aidl
@@ -32,7 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+@VintfStability
+enum ProtectionId {
+  WIDEVINE_OUTPUT_BUFFER = 1,
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricAuthCryptoParameters.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricAuthCryptoParameters.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricAuthCryptoParameters.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricAuthCryptoParameters.aidl
index d3d1763..e42190e 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricAuthCryptoParameters.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricAuthCryptoParameters.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 union SymmetricAuthCryptoParameters {
   android.hardware.security.see.hwcrypto.types.AesGcmMode aes;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricAuthOperationParameters.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricAuthOperationParameters.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricAuthOperationParameters.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricAuthOperationParameters.aidl
index 8a8ef09..78c4a4f 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricAuthOperationParameters.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricAuthOperationParameters.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 parcelable SymmetricAuthOperationParameters {
   android.hardware.security.see.hwcrypto.IOpaqueKey key;
   android.hardware.security.see.hwcrypto.types.SymmetricOperation direction;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricCryptoParameters.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricCryptoParameters.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricCryptoParameters.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricCryptoParameters.aidl
index cc93094..8fd5e85 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricCryptoParameters.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricCryptoParameters.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 union SymmetricCryptoParameters {
   android.hardware.security.see.hwcrypto.types.AesCipherMode aes;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricOperation.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricOperation.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricOperation.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricOperation.aidl
index 1a17525..40fd2d5 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricOperation.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricOperation.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 enum SymmetricOperation {
   ENCRYPT,
   DECRYPT,
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricOperationParameters.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricOperationParameters.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricOperationParameters.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricOperationParameters.aidl
index 769833b..7007074 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/SymmetricOperationParameters.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/SymmetricOperationParameters.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 parcelable SymmetricOperationParameters {
   android.hardware.security.see.hwcrypto.IOpaqueKey key;
   android.hardware.security.see.hwcrypto.types.SymmetricOperation direction;
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/Void.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/Void.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/Void.aidl
rename to security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/Void.aidl
index b37848b..80c91ee 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/Void.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/types/Void.aidl
@@ -32,5 +32,6 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.see.hwcrypto.types;
+@VintfStability
 parcelable Void {
 }
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperation.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperation.aidl
similarity index 99%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperation.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperation.aidl
index 2fdbc78..0859d2a 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperation.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperation.aidl
@@ -25,6 +25,7 @@
  * Type that describes the different operations that can be performed along with its required
  * parameters. It will be used to construct a vector of operation that are executed sequentially.
  */
+@VintfStability
 union CryptoOperation {
     /*
      * Sets a memory buffer to operate on. References to positions of this memory buffer can be used
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationErrorAdditionalInfo.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationErrorAdditionalInfo.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationErrorAdditionalInfo.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationErrorAdditionalInfo.aidl
index f3ac8ea..cc94b02 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationErrorAdditionalInfo.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationErrorAdditionalInfo.aidl
@@ -18,6 +18,7 @@
 /*
  * Type that provides more information about failures when processing a list of commands.
  */
+@VintfStability
 parcelable CryptoOperationErrorAdditionalInfo {
     /*
      * Index indicating the first step of <code>CryptoOperationSet::operations</code> that failed
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationResult.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationResult.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationResult.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationResult.aidl
index 07c2983..5c3b81e 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationResult.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationResult.aidl
@@ -20,6 +20,7 @@
 /*
  * Type that describes the result of a set of crypto operations.
  */
+@VintfStability
 parcelable CryptoOperationResult {
     /*
      * Token that can be passed on a CryptoOperationSet to issue more operations on the same context
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationSet.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationSet.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationSet.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationSet.aidl
index 9aff1e8..285ed36 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationSet.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/CryptoOperationSet.aidl
@@ -21,6 +21,7 @@
 /*
  * Type that describes a set of crypto operations to execute
  */
+@VintfStability
 parcelable CryptoOperationSet {
     /*
      * Token to be used to issue the operations. If NULL, a new context will be created and
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/ICryptoOperationContext.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/ICryptoOperationContext.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/ICryptoOperationContext.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/ICryptoOperationContext.aidl
index 68d0c03..8cfa735 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/ICryptoOperationContext.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/ICryptoOperationContext.aidl
@@ -22,4 +22,5 @@
  * operation in progress context includes any memory buffer previously mapped by a
  * <code>CryptoOperation::SetMemoryBuffer</code> call.
  */
+@VintfStability
 interface ICryptoOperationContext {}
diff --git a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
new file mode 100644
index 0000000..93d6cbc
--- /dev/null
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.security.see.hwcrypto;
+
+import android.hardware.security.see.hwcrypto.IHwCryptoOperations;
+import android.hardware.security.see.hwcrypto.IOpaqueKey;
+import android.hardware.security.see.hwcrypto.KeyPolicy;
+import android.hardware.security.see.hwcrypto.types.ExplicitKeyMaterial;
+import android.hardware.security.see.hwcrypto.types.OpaqueKeyToken;
+
+/*
+ * Higher level interface to access and generate keys.
+ */
+@VintfStability
+interface IHwCryptoKey {
+    /*
+     * Identifier for the requested device provided key. The currently supported identifiers are:
+     *
+     */
+    enum DeviceKeyId {
+        /*
+         * This is a key unique to the device.
+         */
+        DEVICE_BOUND_KEY,
+    }
+
+    /*
+     * Identifier for the requested key slot. The currently supported identifiers are:
+     *
+     */
+    enum KeySlot {
+        /*
+         * This is the shared HMAC key that will now be computed by HwCryptoKey after participating
+         * in the ISharedSecret protocol that can be shared with KeyMint and authenticators. See
+         * ISharedSecret.aidl for more information.
+         */
+        KEYMINT_SHARED_HMAC_KEY,
+    }
+
+    union DiceBoundDerivationKey {
+        /*
+         * Opaque to be used to derive the DICE bound key.
+         */
+        IOpaqueKey opaqueKey;
+
+        /*
+         * Device provided key to be used to derive the DICE bound key.
+         */
+        DeviceKeyId keyId;
+    }
+
+    parcelable DiceCurrentBoundKeyResult {
+        /*
+         * Key cryptographically bound to a DICE policy.
+         */
+        IOpaqueKey diceBoundKey;
+
+        /*
+         * Current dice policy which was used to generate the returned key. This policy is opaque
+         * from this service perspective (it will be sent to an Authentication Manager Service to be
+         * verified). It follows the structure defined on DicePolicy.cddl, located under
+         * hardware/interfaces/security/authgraph/aidl/android/hardware/security/authgraph/ with the
+         * caveat that it could be encrypted if the client does not have enough permissions to see
+         * the device dice policy information.
+         */
+        byte[] dicePolicyForKeyVersion;
+    }
+
+    parcelable DiceBoundKeyResult {
+        /*
+         * Key cryptographically bound to a DICE policy.
+         */
+        IOpaqueKey diceBoundKey;
+
+        /*
+         * Indicates if the diceBoundKey returned was created using a current DICE policy. The
+         * caller can use this to detect if an old policy was provided and rotate its keys if so
+         * desired. Old, valid policies remain usable, but care needs to be taken to not continue to
+         * use a potentially compromised key.
+         */
+        boolean dicePolicyWasCurrent;
+    }
+
+    parcelable ClearKeyPolicy {
+        /*
+         * Indicates the desired key size. It will be used to calculate how many bytes of key
+         * material should be returned.
+         */
+        int keySizeBytes;
+    }
+
+    union DerivedKeyPolicy {
+        /*
+         * If used we will derive a clear key and pass it back as an array of bytes on
+         * <code>HwCryptoKeyMaterial::explicitKey</code>.
+         */
+        ClearKeyPolicy clearKeyPolicy;
+
+        /*
+         * Policy for the newly derived opaque key. Defines how the key can be used and its type.
+         * Its definition can be found in <code>KeyPolicy.cddl</code>, which is basically a CBOR
+         * serialization of the file <code>KeyPolicy.aidl</code>.
+         */
+        byte[] opaqueKey;
+    }
+
+    parcelable DerivedKeyParameters {
+        /*
+         * Key to be used to derive the new key using HKDF.
+         */
+        IOpaqueKey derivationKey;
+
+        /*
+         * Policy for the newly derived key. Depending on its type, either a clear or opaque key
+         * will be derived.
+         */
+        DerivedKeyPolicy keyPolicy;
+
+        /*
+         * An arbitrary set of bytes incorporated into the key derivation. May have an
+         * implementation-specific maximum length, but it is guaranteed to accept at least 32 bytes.
+         */
+        byte[] context;
+    }
+
+    union DerivedKey {
+        /*
+         * Derived key in clear format.
+         */
+        byte[] explicitKey = {};
+
+        /*
+         * Derived key as a key token to be used only through the HWCrypto service.
+         */
+        IOpaqueKey opaque;
+    }
+
+    /*
+     * Derives a versioned key tied to the caller's current DICE policy. It will return this current
+     * policy back to the caller along with the generated key.
+     *
+     * @param derivationKey:
+     *     Key to be used to derive the new key using HKDF.
+     *
+     * @return:
+     *     A DiceCurrentBoundKeyResult containing the versioned key tied the current client version
+     *     on success.
+     *
+     * @throws:
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - BAD_PARAMETER if an invalid DeviceKeyId is requested.
+     *          - INVALID_KEY if an opaque key is provided that is not suitable for key derivation.
+     */
+    DiceCurrentBoundKeyResult deriveCurrentDicePolicyBoundKey(
+            in DiceBoundDerivationKey derivationKey);
+
+    /*
+     * Derive a versioned key by checking the provided DICE policy against the caller and then using
+     * it as a context for deriving the returned key.
+     *
+     * @param derivationKey:
+     *     Key to be used to derive the new key using HKDF.
+     *
+     * @param dicePolicyForKeyVersion:
+     *     Policy used to derive keys tied to specific versions. Using this parameter the caller can
+     *     tie a derived key to a minimum version of itself, so in the future only itself or a more
+     *     recent version can derive the same key. This parameter is opaque to the caller and it
+     *     could be encrypted in the case the client doesn't have permission to know the dice chain.
+     *     When implementing this function, this parameter shall be one of the components fed to the
+     *     KDF context and it needs to be checked against the caller DICE certificate before being
+     *     used.
+     *
+     * @return:
+     *      A DiceBoundKeyResult containing the versioned key tied to the provided DICE policy on
+     *      success.
+     *
+     * @throws:
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - BAD_PARAMETER if an invalid DeviceKeyId is requested or if dicePolicyForKeyVersion
+     *            is not a valid encrypted DICE policy.
+     *          - INVALID_KEY if an opaque key is provided that is not suitable for key derivation.
+     */
+    DiceBoundKeyResult deriveDicePolicyBoundKey(
+            in DiceBoundDerivationKey derivationKey, in byte[] dicePolicyForKeyVersion);
+
+    /*
+     * Derive a new key based on the given key, policy and context.
+     *
+     * @param parameters:
+     *      Parameters used for the key derivation. See <code>DerivedKeyParameters</code> on this
+     *      file for more information.
+     *
+     * @return:
+     *      A <code>DerivedKey</code> containing the derived key on success.
+     *
+     * @throws:
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - BAD_PARAMETER if an invalid key policy is provided or if the key policy conflicts
+     *            with the requested key.
+     *          - SERIALIZATION_ERROR if the provided key policy is not a valid CBOR key policy.
+     *          - INVALID_KEY if an opaque key is provided that is not suitable for key derivation.
+     */
+    DerivedKey deriveKey(in DerivedKeyParameters parameters);
+
+    /*
+     * Returns an interface used to work on opaque keys. This interface can also be used to operate
+     * on any opaque key generated by hwkeyDeriveVersioned, even if this key has been generated
+     * after retrieving a IHwCryptoOperations binder object, as long as the parent
+     * IHwCryptoDeviceKeyAccess is not dropped between retrieving the IHwCryptoOperations binder
+     * object and deriving the key. IHwCryptoOperations can also be used to create opaque keys that
+     * are not bound to the device.
+     *
+     * @return:
+     *      IHwCryptoOperations on success
+     */
+    IHwCryptoOperations getHwCryptoOperations();
+
+    /*
+     * Imports a SW clear key into the secure environment.
+     *
+     * @param keyMaterial:
+     *     key to be imported.
+     *
+     * @param newKeyPolicy:
+     *      Policy of the new key. Defines how the newly created key can be used. Because any clear
+     *      key imported into the system is considered to have a <code>KeyLifetime::PORTABLE</code>
+     *      lifetime, a call to this function will return an error if
+     *      <code>newKeyPolicy.newKeyPolicy</code> is not set to portable.
+     *
+     * @return:
+     *      IOpaqueKey on success.
+     *
+     * @throws:
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - BAD_PARAMETER if an invalid Key policy is provided or if the key policy conflicts
+     *            with provided key material.
+     *          - ALLOCATION_ERROR if the system runs out of memory while carring out the operation.
+     */
+    IOpaqueKey importClearKey(in ExplicitKeyMaterial keyMaterial, in KeyPolicy newKeyPolicy);
+
+    /*
+     * Returns the client current DICE policy. This policy is encrypted and considered opaque from
+     * the client perspective. This policy is the same used to create DICE bound keys and will also
+     * be used to seal secrets that can only be retrieved by the DICE policy owner. The first use of
+     * this seal operation will be <code>IOpaqueKey::getShareableToken</code> and will call this
+     * <code>IHwCryptoKey::keyTokenImport</code>. To start this process, the intended key receiver
+     * function and then pass the generated DICE policy to the owner of the key that the receiver
+     * wants to import. The key owner will then call <code>IOpaqueKey::getShareableToken</code>
+     * passing the receiver DICE policy to insure that only that receiver can import the key.
+     *
+     * @return:
+     *      byte[] on success, which is the caller encrypted DICE policy. The DICE policy follows
+     *      the structure defined on DicePolicy.cddl, located under
+     *      hardware/interfaces/security/authgraph/aidl/android/hardware/security/authgraph/
+     */
+    byte[] getCurrentDicePolicy();
+
+    /*
+     * Imports a key from a different client service instance. Because IOpaqueKey are binder objects
+     * that cannot be directly shared between binder rpc clients, this method provide a way to send
+     * a key to another client. Keys to be imported by the receiver are represented by a token
+     * created using <code>IOpaqueKey::getShareableToken</code>. The flow to create this token is
+     * described in <code>IHwCryptoKey::getCurrentDicePolicy</code>.
+     *
+     * @param requested_key:
+     *      Handle to the key to be imported to the caller service.
+     *
+     * @param sealingDicePolicy:
+     *      DICE policy used to seal the exported key.
+     *
+     * @return:
+     *      An IOpaqueKey that can be directly used on the local HWCrypto service on success.
+     *
+     * @throws:
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - BAD_PARAMETER if an invalid encrypted sealing DICE policy is provided.
+     *          - ALLOCATION_ERROR if the system runs out of memory while carring out the operation.
+     *          - UNAUTHORIZED if the sealingDicePolicy do not match the caller.
+     */
+    IOpaqueKey keyTokenImport(in OpaqueKeyToken requestedKey, in byte[] sealingDicePolicy);
+
+    /*
+     * Gets the keyslot key material referenced by slotId. This interface is used to access device
+     * specific keys with known types and uses. Because the returned key is opaque, it can only be
+     * used through the different HwCrypto interfaces. Because the keys live in a global namespace
+     * the identity of the caller needs to be checked to verify that it has permission to access the
+     * requested key.
+     *
+     * @param slotId:
+     *      Identifier for the requested keyslot
+     *
+     * @return:
+     *      An IOpaqueKey corresponding to the requested key slot on success.
+     *
+     * @throws:
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - UNAUTHORIZED if the caller cannot access the requested key.
+     */
+    IOpaqueKey getKeyslotData(KeySlot slotId);
+}
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
similarity index 62%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
index 4d394ed..dbe4d80 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
@@ -24,21 +24,28 @@
  * cryptographic keys. Interactions with this interface are done through a command-base API,
  * which allow callers to execute a large set of operations on a single call.
  */
+@VintfStability
 interface IHwCryptoOperations {
     /*
-     * processCommandList() - Executes a list of cryptographic commands in order
+     * Executes a list of cryptographic commands in order
      *
-     * @operations:
+     * @param operations:
      *      Parameter containing 1 or more set of commands to execute. Additionally, each set can
-     *      also contain a context on which the commands will be executed.
-     * @additionalErrorInfo:
-     *      Structure containing additional info when errors are encountered. Only valid if the
-     *      function failed its execution.
-     * Return:
+     *      also contain a context on which the commands will be executed. The parameter has type
+     *      inout because it can contain buffers used to write the output of the operation.
+     *
+     * @return:
      *      CryptoOperationResult[] on success, which can contain a context to continue executing
-     *      each of the provided operations sets, service specific error based on
-     *      <code>HalErrorCode</code> otherwise.
+     *      each of the provided operations sets.
+     *
+     * @throws:
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - INVALID_KEY if the provided key is not compatible with the operation requested.
+     *          - BAD_STATE if the provided <code>CryptoOperationSet</code> contains operations that
+     *            cannot be carried out in the current server state.
+     *          - UNSUPPORTED if the requested operation is not supported by the server.
+     *          - ALLOCATION_ERROR if the system runs out of memory while carring out the operation.
      */
-    CryptoOperationResult[] processCommandList(inout CryptoOperationSet[] operations,
-            out CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+    CryptoOperationResult[] processCommandList(inout CryptoOperationSet[] operations);
 }
diff --git a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IOpaqueKey.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IOpaqueKey.aidl
new file mode 100644
index 0000000..318a27e
--- /dev/null
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IOpaqueKey.aidl
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.security.see.hwcrypto;
+
+import android.hardware.security.see.hwcrypto.KeyPolicy;
+import android.hardware.security.see.hwcrypto.types.OpaqueKeyToken;
+import android.hardware.security.see.hwcrypto.types.OperationType;
+import android.hardware.security.see.hwcrypto.types.ProtectionId;
+
+@VintfStability
+interface IOpaqueKey {
+    /*
+     * Exports this key as a wrapped (encrypted) blob.
+     *
+     * @param wrapping_key:
+     *     wrapping key. It needs to be an opaque key and its policy needs to indicate that it can
+     *     be used for key wrapping.
+     *
+     * @return:
+     *      Wrapped key blob as a byte array on success. Format of the blob is opaque to the service
+     *      but has to match the command accepted by
+     *      <code>IHwCryptoKeyGeneration::importWrappedKey</code>
+     *
+     * @throws:
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+     */
+    byte[] exportWrappedKey(in IOpaqueKey wrappingKey);
+
+    /*
+     * Returns the key policy.
+     *
+     * @return:
+     *      A <code>KeyPolicy</code> on success
+     *
+     * @throws:
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+     */
+    KeyPolicy getKeyPolicy();
+
+    /*
+     * Returns the public key portion of this OpaqueKey. This operation is only valid for asymmetric
+     * keys.
+     *
+     * @return:
+     *      public key as a byte array on success. Format used for the returned public key is COSE.
+     *
+     * @throws:
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+     */
+    byte[] getPublicKey();
+
+    /*
+     * Returns a token that can shared with another HWCrypto client.
+     *
+     * @param sealingDicePolicy:
+     *      Token to be used to protect the returned OpaqueKeyToken. It will be used so only
+     *      the owner of the sealingDicePolicy can import the key.
+     *
+     * @return:
+     *      <code>OpaqueKeyMaterial</code> token on success.
+     *
+     * @throws:
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+     */
+    OpaqueKeyToken getShareableToken(in byte[] sealingDicePolicy);
+
+    /*
+     * Sets the protectionID associated with the buffers where the operation will be performed. A
+     * protection ID serves as a limitation on the key so it can only operate on buffers with a
+     * matching protection ID. The client calling this functions needs to have the necessary
+     * permissions to read and/or write to this buffer. Setting this parameter means that if the key
+     * is shared with a different client, the client receiving the key will be limited in which
+     * buffers can be used to read/write data for this operation.
+     *
+     * @param protectionId:
+     *      ID of the given use case to provide protection for. The method of protecting the buffer
+     *      will be platform dependent.
+     *
+     * @param allowedOperations:
+     *      array of allowed operations. Allowed operations are either READ or WRITE.
+     *
+     * @throws:
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+     */
+    void setProtectionId(in ProtectionId protectionId, in OperationType[] allowedOperations);
+}
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/KeyPolicy.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/KeyPolicy.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/KeyPolicy.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/KeyPolicy.aidl
index 9266bfa..a20e99b 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/KeyPolicy.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/KeyPolicy.aidl
@@ -23,6 +23,7 @@
 /*
  * Parcelable that specified how a key can be used.
  */
+@VintfStability
 parcelable KeyPolicy {
     /*
      * Enum specifying the operations the key can perform (encryption, decryption, etc.).
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/KeyPolicy.cddl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/KeyPolicy.cddl
similarity index 100%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/KeyPolicy.cddl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/KeyPolicy.cddl
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
index c5a6a5c..efc5767 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
@@ -18,6 +18,7 @@
 /*
  * Parcelable representing a memory buffer.
  */
+@VintfStability
 parcelable MemoryBufferParameter {
     union MemoryBuffer {
         ParcelFileDescriptor input;
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/OperationParameters.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/OperationParameters.aidl
similarity index 85%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/OperationParameters.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/OperationParameters.aidl
index 9e2fc6c..bf0b720 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/OperationParameters.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/OperationParameters.aidl
@@ -15,12 +15,14 @@
  */
 package android.hardware.security.see.hwcrypto;
 
+import android.hardware.security.see.hwcrypto.types.HmacOperationParameters;
 import android.hardware.security.see.hwcrypto.types.SymmetricAuthOperationParameters;
 import android.hardware.security.see.hwcrypto.types.SymmetricOperationParameters;
 
 /*
  * Type that describes the parameters for the different operations that can be performed.
  */
+@VintfStability
 union OperationParameters {
     /*
      * Parameters for authenticated symmetric cryptography (AES GCM).
@@ -31,4 +33,9 @@
      * Parameters for non-authenticated symmetric cryptography (AES/TDES).
      */
     SymmetricOperationParameters symmetricCrypto;
+
+    /*
+     * Parameters for hash based message authenticated code operations.
+     */
+    HmacOperationParameters hmac;
 }
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/PatternParameters.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/PatternParameters.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/PatternParameters.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/PatternParameters.aidl
index 3f62abe..9f8950f 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/PatternParameters.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/PatternParameters.aidl
@@ -18,6 +18,7 @@
 /*
  * Parcelable that specifies a pattern to process data.
  */
+@VintfStability
 parcelable PatternParameters {
     /*
      * Number of blocks that will be processed. The size of the block matches the size of the
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesCipherMode.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesCipherMode.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesCipherMode.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesCipherMode.aidl
index ac31557..8ce83aa 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesCipherMode.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesCipherMode.aidl
@@ -21,6 +21,7 @@
 /*
  * Type used for the parameters needed to run a non-authenticated AES operation.
  */
+@VintfStability
 union AesCipherMode {
     /*
      * Cipher Block Chaining mode. Padding will either be none or PKCS#7 depending on the key policy
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl
index 4025553..1c6551c 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl
@@ -18,6 +18,7 @@
 /*
  * Type used for the parameters needed to run an authenticated AES operation (GCM).
  */
+@VintfStability
 union AesGcmMode {
     parcelable AesGcmModeParameters {
         /*
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesKey.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesKey.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesKey.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesKey.aidl
index cf9082d..ae62ef9 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesKey.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesKey.aidl
@@ -18,6 +18,7 @@
 /*
  * Type that represents an AES key.
  */
+@VintfStability
 union AesKey {
     /*
      * Raw AES 128 bit key material.
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl
similarity index 88%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl
index bfa5daa..e7ede57 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl
@@ -19,6 +19,10 @@
 /*
  * Type encapsulating nonce used on non-authenticated AES symmetric encryption.
  */
+@VintfStability
 parcelable CipherModeParameters {
+    /*
+     * nonce to be used as IV for AES-CBC or as the nonce in AES-CTR
+     */
     byte[16] nonce;
 }
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
similarity index 81%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
index 4298ba9..a5bf594 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ExplicitKeyMaterial.aidl
@@ -16,10 +16,20 @@
 package android.hardware.security.see.hwcrypto.types;
 
 import android.hardware.security.see.hwcrypto.types.AesKey;
+import android.hardware.security.see.hwcrypto.types.HmacKey;
 
 /*
  * Type encapsulating a clear key.
  */
+@VintfStability
 union ExplicitKeyMaterial {
+    /*
+     * AES key in clear format.
+     */
     AesKey aes;
+
+    /*
+     * HMAC key in clear format.
+     */
+    HmacKey hmac;
 }
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/HalErrorCode.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/HalErrorCode.aidl
similarity index 93%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/HalErrorCode.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/HalErrorCode.aidl
index e8e8539..df12262 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/HalErrorCode.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/HalErrorCode.aidl
@@ -18,6 +18,7 @@
 /*
  * Service error codes. Will be returned as service specific errors.
  */
+@VintfStability
 parcelable HalErrorCode {
     /* Success */
     const int NO_ERROR = 0;
@@ -42,4 +43,7 @@
 
     /* Bad parameter supplied for the desired operation */
     const int BAD_PARAMETER = -7;
+
+    /* Caller is not authorized to make this call */
+    const int UNAUTHORIZED = -8;
 }
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesKey.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/HmacKey.aidl
similarity index 69%
copy from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesKey.aidl
copy to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/HmacKey.aidl
index cf9082d..b1a988e 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesKey.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/HmacKey.aidl
@@ -16,16 +16,18 @@
 package android.hardware.security.see.hwcrypto.types;
 
 /*
- * Type that represents an AES key.
+ * Type that represents an Hmac key.
  */
-union AesKey {
+@VintfStability
+union HmacKey {
     /*
-     * Raw AES 128 bit key material.
+     * Raw Hmac key for use with sha256.
      */
-    byte[16] aes128 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    byte[32] sha256 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0};
 
     /*
-     * Raw AES 256 bit key material.
+     * Raw Hmac key for use with sha512.
      */
-    byte[32] aes256;
+    byte[64] sha512;
 }
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/HmacOperationParameters.aidl
similarity index 74%
copy from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl
copy to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/HmacOperationParameters.aidl
index bfa5daa..faa3072 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/CipherModeParameters.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/HmacOperationParameters.aidl
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2024 The Android Open Source Project
  *
@@ -16,9 +15,14 @@
  */
 package android.hardware.security.see.hwcrypto.types;
 
+import android.hardware.security.see.hwcrypto.IOpaqueKey;
 /*
- * Type encapsulating nonce used on non-authenticated AES symmetric encryption.
+ * Data needed to perform HMAC operations.
  */
-parcelable CipherModeParameters {
-    byte[16] nonce;
+@VintfStability
+parcelable HmacOperationParameters {
+    /*
+     * Key to be used for the HMAC operation.
+     */
+    IOpaqueKey key;
 }
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyLifetime.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyLifetime.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyLifetime.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyLifetime.aidl
index 9958a0b..b03b850 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyLifetime.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyLifetime.aidl
@@ -20,6 +20,7 @@
  * represented as a bitmask to allow us to internally combine them on a single property to describe
  * a set of allowed lifetimes.
  */
+@VintfStability
 @Backing(type="byte")
 enum KeyLifetime {
     /*
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
index a1e4f21..c48ef8b 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyPermissions.aidl
@@ -18,6 +18,7 @@
 /*
  * Additional characteristics and permissions of the key.
  */
+@VintfStability
 enum KeyPermissions {
     /*
      * Key can be wrapped by an ephemeral key.
diff --git a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyType.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyType.aidl
new file mode 100644
index 0000000..ed90899
--- /dev/null
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyType.aidl
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.security.see.hwcrypto.types;
+
+/*
+ * Enum describing all supported key types. Key types are strongly bound to the algorithm to
+ * prevent reusing the same key on different algorithms (e.g. using the same key for 2 different AES
+ * 128 Cipher modes).
+ */
+@VintfStability
+enum KeyType {
+    /*
+     * AES with key size 128 bits using CBC mode of operation and no padding.
+     */
+    AES_128_CBC_NO_PADDING,
+
+    /*
+     * AES with key size 128 bits using CBC mode of operation and PKCS7 padding.
+     */
+    AES_128_CBC_PKCS7_PADDING,
+
+    /*
+     * AES with key size 128 bits using counter mode.
+     */
+    AES_128_CTR,
+
+    /*
+     * AES with key size 128 bits using GCM mode for authenticated encryption.
+     */
+    AES_128_GCM,
+
+    /*
+     * AES with key size 128 bits for CMAC calculation.
+     */
+    AES_128_CMAC,
+
+    /*
+     * AES with key size 256 bits using CBC mode of operation and no padding.
+     */
+    AES_256_CBC_NO_PADDING,
+
+    /*
+     * AES with key size 256 bits using CBC mode of operation and PKCS7 padding.
+     */
+    AES_256_CBC_PKCS7_PADDING,
+
+    /*
+     * AES with key size 128 bits using counter mode.
+     */
+    AES_256_CTR,
+
+    /*
+     * AES with key size 128 bits using GCM mode for authenticated encryption.
+     */
+    AES_256_GCM,
+
+    /*
+     * AES with key size 128 bits for CMAC calculation.
+     */
+    AES_256_CMAC,
+
+    /*
+     * Key of length of 32 bytes for HMAC operations using SHA256.
+     */
+    HMAC_SHA256,
+
+    /*
+     * Key of length of 64 bytes for HMAC operations using SHA512.
+     */
+    HMAC_SHA512,
+
+    /*
+     * RSA of key size of 2048 bits for signing using PSS.
+     */
+    RSA2048_PSS_SHA256,
+
+    /*
+     * RSA of key size of 2048 bits for signing with padding PKCS 1.5 and SHA256 as the digest
+     * algorithm.
+     */
+    RSA2048_PKCS1_5_SHA256,
+
+    /*
+     * ECC key for signing using curve P-256 and no padding.
+     */
+    ECC_NIST_P256_SIGN_NO_PADDING,
+
+    /*
+     * ECC key for signing using curve P-256 and SHA256 as hashing algorithm.
+     */
+    ECC_NIST_P256_SIGN_SHA256,
+
+    /*
+     * ECC key for signing using curve P-521 and no padding.
+     */
+    ECC_NIST_P521_SIGN_NO_PADDING,
+
+    /*
+     * ECC key for signing using curve P-512 and SHA512 as hashing algorithm.
+     */
+    ECC_NIST_P521_SIGN_SHA512,
+
+    /*
+     * ECC key for signing using EdDSA.
+     */
+    ECC_ED25519_SIGN,
+}
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyUse.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyUse.aidl
similarity index 77%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyUse.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyUse.aidl
index 76bfd62..60bfd06 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyUse.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyUse.aidl
@@ -18,12 +18,24 @@
 /*
  * Enum describing the allowed operations that can be performed with the given key.
  */
+@VintfStability
 @Backing(type="int")
 enum KeyUse {
+    /* Key can be used to encrypt */
     ENCRYPT = 1,
+
+    /* Key can be used to decrypt */
     DECRYPT = 2,
+
+    /* Key can be used to encrypt or decrypt */
     ENCRYPT_DECRYPT = ENCRYPT | DECRYPT,
+
+    /* Key can be used to sign */
     SIGN = 4,
+
+    /* Key can be used to derive other keys */
     DERIVE = 8,
+
+    /* Key can be used to wrap other keys */
     WRAP = 16,
 }
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/MemoryBufferReference.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/MemoryBufferReference.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/MemoryBufferReference.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/MemoryBufferReference.aidl
index 1175dc5..0f3c099 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/MemoryBufferReference.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/MemoryBufferReference.aidl
@@ -18,6 +18,7 @@
 /*
  * Structure representing a section of a memory buffer.
  */
+@VintfStability
 @RustDerive(Copy=true, Clone=true)
 parcelable MemoryBufferReference {
     /*
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OpaqueKeyToken.aidl
similarity index 63%
copy from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl
copy to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OpaqueKeyToken.aidl
index 4025553..25cc6fb 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/AesGcmMode.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OpaqueKeyToken.aidl
@@ -16,18 +16,15 @@
 package android.hardware.security.see.hwcrypto.types;
 
 /*
- * Type used for the parameters needed to run an authenticated AES operation (GCM).
+ * Implementation defined structure that represents a key and its associated metadata. It is only
+ * valid on the current boot, and its reuse after a session is closed (or between sessions) is not
+ * guaranteed.
  */
-union AesGcmMode {
-    parcelable AesGcmModeParameters {
-        /*
-         * Galois Counter Mode nonce. Only 12-bytes nonce are supported.
-         */
-        byte[12] nonce;
-    }
-
+@VintfStability
+parcelable OpaqueKeyToken {
     /*
-     * Galois Counter Mode with an authentication Tag that has a length of 16 bytes.
+     * Opaque type used to send IOpaqueKeys keys to different clients. Its format is implementation
+     * dependant.
      */
-    AesGcmModeParameters gcmTag16;
+    byte[] keyToken;
 }
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OperationData.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OperationData.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OperationData.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OperationData.aidl
index 642d05e..8dfca72 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OperationData.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OperationData.aidl
@@ -20,6 +20,7 @@
 /*
  * Union holding buffers to be used by the cryptographic operation.
  */
+@VintfStability
 union OperationData {
     /*
      * Reference (offset, size) to the active operations' MemoryBuffer.
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OperationType.aidl
similarity index 90%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OperationType.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OperationType.aidl
index 76878a3..2dc9ae9 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/OperationType.aidl
@@ -18,7 +18,11 @@
 /*
  * Enum describing the different types of operations allowed on a buffer.
  */
+@VintfStability
 enum OperationType {
+    /* Read operations allowed*/
     READ,
+
+    /* Write operations allowed*/
     WRITE,
 }
diff --git a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ProtectionId.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ProtectionId.aidl
new file mode 100644
index 0000000..8fd0551
--- /dev/null
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/ProtectionId.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.security.see.hwcrypto.types;
+
+/*
+ * Enum describing the different types of protected buffers. Protected buffers are named by its
+ * corresponding use case and its underlaying implementation is platform dependant.
+ */
+@VintfStability
+enum ProtectionId {
+    /*
+     * ProtectionID used by HwCrypto to enable Keys that can be used for Widevine video buffers.
+     * These buffers should not be readable by non-trusted entities and HwCrypto should not allow
+     * any read access to them through its interface.
+     */
+    WIDEVINE_OUTPUT_BUFFER = 1,
+}
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricAuthCryptoParameters.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricAuthCryptoParameters.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricAuthCryptoParameters.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricAuthCryptoParameters.aidl
index 278e48d..79c39f9 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricAuthCryptoParameters.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricAuthCryptoParameters.aidl
@@ -20,6 +20,7 @@
 /*
  * Data needed to perform authenticated symmetric cryptographic operations.
  */
+@VintfStability
 union SymmetricAuthCryptoParameters {
     /*
      * AES (Advanced Encryption Standard) GCM parameters.
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricAuthOperationParameters.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricAuthOperationParameters.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricAuthOperationParameters.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricAuthOperationParameters.aidl
index 46568c3..844a3bc 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricAuthOperationParameters.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricAuthOperationParameters.aidl
@@ -23,6 +23,7 @@
  * Parameters needed to perform an authenticated symmetric cryptographic operation. Currently only
  * AES-GCM is supported.
  */
+@VintfStability
 parcelable SymmetricAuthOperationParameters {
     /*
      * Key to be used on the operation.
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricCryptoParameters.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricCryptoParameters.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricCryptoParameters.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricCryptoParameters.aidl
index 2350242..679fe6a 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricCryptoParameters.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricCryptoParameters.aidl
@@ -20,6 +20,7 @@
 /*
  * Data needed to perform non-authenticated symmetric cryptographic operations.
  */
+@VintfStability
 union SymmetricCryptoParameters {
     /*
      * AES (Advanced Encryption Standard) parameters.
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricOperation.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricOperation.aidl
similarity index 92%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricOperation.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricOperation.aidl
index 2717472..d88d4e9 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricOperation.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricOperation.aidl
@@ -18,4 +18,4 @@
 /*
  * Enum describing the type of symmetric operation desired.
  */
-enum SymmetricOperation { ENCRYPT, DECRYPT }
+@VintfStability enum SymmetricOperation { ENCRYPT, DECRYPT }
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricOperationParameters.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricOperationParameters.aidl
similarity index 98%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricOperationParameters.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricOperationParameters.aidl
index 1d1554d..509d416 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricOperationParameters.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/SymmetricOperationParameters.aidl
@@ -22,6 +22,7 @@
 /*
  * Parameters needed to perform a non-authenticated symmetric cryptographic operation.
  */
+@VintfStability
 parcelable SymmetricOperationParameters {
     /*
      * Key to be used on the operation.
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/Void.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/Void.aidl
similarity index 92%
rename from staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/Void.aidl
rename to security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/Void.aidl
index f9f608d..243fb45 100644
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/Void.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/Void.aidl
@@ -15,4 +15,8 @@
  */
 package android.hardware.security.see.hwcrypto.types;
 
+/*
+ * Type used to represent no data.
+ */
+@VintfStability
 parcelable Void {}
diff --git a/staging/security/see/storage/aidl/Android.bp b/security/see/storage/aidl/Android.bp
similarity index 91%
rename from staging/security/see/storage/aidl/Android.bp
rename to security/see/storage/aidl/Android.bp
index f669be8..279cb90 100644
--- a/staging/security/see/storage/aidl/Android.bp
+++ b/security/see/storage/aidl/Android.bp
@@ -4,7 +4,7 @@
 
 aidl_interface {
     name: "android.hardware.security.see.storage",
-    unstable: true,
+    stability: "vintf",
     host_supported: true,
     srcs: [
         "android/hardware/security/see/storage/*.aidl",
@@ -23,4 +23,5 @@
             enabled: true,
         },
     },
+    frozen: false,
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/Availability.aidl
similarity index 92%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/Availability.aidl
index ca8b3eb..62af569 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/Availability.aidl
@@ -31,8 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.security.see.storage;
+@VintfStability
+enum Availability {
+  BEFORE_USERDATA,
+  AFTER_USERDATA,
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/CreationMode.aidl
similarity index 92%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/CreationMode.aidl
index ca8b3eb..f999205 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/CreationMode.aidl
@@ -31,8 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.security.see.storage;
+@VintfStability
+enum CreationMode {
+  NO_CREATE,
+  CREATE_EXCLUSIVE,
+  CREATE,
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/FileMode.aidl
similarity index 92%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/FileMode.aidl
index ca8b3eb..604e61f 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/FileMode.aidl
@@ -31,8 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.security.see.storage;
+@VintfStability
+enum FileMode {
+  READ_ONLY,
+  WRITE_ONLY,
+  READ_WRITE,
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/Filesystem.aidl
similarity index 81%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
copy to security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/Filesystem.aidl
index 5c26cc2..df08380 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/Filesystem.aidl
@@ -31,7 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-interface IHwCryptoOperations {
-  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+package android.hardware.security.see.storage;
+@VintfStability
+parcelable Filesystem {
+  android.hardware.security.see.storage.Integrity integrity = android.hardware.security.see.storage.Integrity.TAMPER_PROOF_AT_REST;
+  android.hardware.security.see.storage.Availability availability = android.hardware.security.see.storage.Availability.BEFORE_USERDATA;
+  boolean persistent;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/IDir.aidl
similarity index 91%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/IDir.aidl
index ca8b3eb..7068ea2 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/IDir.aidl
@@ -31,8 +31,8 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.security.see.storage;
+@VintfStability
+interface IDir {
+  @utf8InCpp String[] readNextFilenames(int maxCount);
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/IFile.aidl
similarity index 83%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
copy to security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/IFile.aidl
index d88d5c8..734ec0c 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/MemoryBufferParameter.aidl
+++ b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/IFile.aidl
@@ -31,12 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-parcelable MemoryBufferParameter {
-  android.hardware.security.see.hwcrypto.MemoryBufferParameter.MemoryBuffer bufferHandle;
-  int sizeBytes;
-  union MemoryBuffer {
-    ParcelFileDescriptor input;
-    ParcelFileDescriptor output;
-  }
+package android.hardware.security.see.storage;
+@VintfStability
+interface IFile {
+  byte[] read(long size, long offset);
+  long write(long offset, in byte[] buffer);
+  long getSize();
+  void setSize(long newSize);
+  void rename(in @utf8InCpp String destPath, in android.hardware.security.see.storage.CreationMode destCreateMode);
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/ISecureStorage.aidl
similarity index 78%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
copy to security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/ISecureStorage.aidl
index 5c26cc2..c99c039 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/ISecureStorage.aidl
@@ -31,7 +31,14 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-interface IHwCryptoOperations {
-  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+package android.hardware.security.see.storage;
+@VintfStability
+interface ISecureStorage {
+  android.hardware.security.see.storage.IStorageSession startSession(in android.hardware.security.see.storage.Filesystem filesystem);
+  const int ERR_UNSUPPORTED_PROPERTIES = 1;
+  const int ERR_NOT_FOUND = 2;
+  const int ERR_ALREADY_EXISTS = 3;
+  const int ERR_BAD_TRANSACTION = 4;
+  const int ERR_AB_UPDATE_IN_PROGRESS = 5;
+  const int ERR_FS_TAMPERED = 6;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/IStorageSession.aidl
similarity index 72%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
copy to security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/IStorageSession.aidl
index 5c26cc2..11b4b9a 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/IStorageSession.aidl
@@ -31,7 +31,14 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-interface IHwCryptoOperations {
-  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+package android.hardware.security.see.storage;
+@VintfStability
+interface IStorageSession {
+  void commitChanges();
+  void stageChangesForCommitOnAbUpdateComplete();
+  void abandonChanges();
+  android.hardware.security.see.storage.IFile openFile(in @utf8InCpp String filePath, in android.hardware.security.see.storage.OpenOptions options);
+  void deleteFile(in @utf8InCpp String filePath);
+  void renameFile(in @utf8InCpp String currentPath, in @utf8InCpp String destPath, in android.hardware.security.see.storage.CreationMode destCreateMode);
+  android.hardware.security.see.storage.IDir openDir(in @utf8InCpp String path);
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/Integrity.aidl
similarity index 92%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/Integrity.aidl
index ca8b3eb..801da04 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/Integrity.aidl
@@ -31,8 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.security.see.storage;
+@VintfStability
+enum Integrity {
+  TAMPER_PROOF_AT_REST,
+  TAMPER_DETECT,
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/OpenOptions.aidl
similarity index 81%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
copy to security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/OpenOptions.aidl
index 5c26cc2..eda2404 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/storage/aidl/aidl_api/android.hardware.security.see.storage/current/android/hardware/security/see/storage/OpenOptions.aidl
@@ -31,7 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto;
-interface IHwCryptoOperations {
-  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+package android.hardware.security.see.storage;
+@VintfStability
+parcelable OpenOptions {
+  android.hardware.security.see.storage.CreationMode createMode = android.hardware.security.see.storage.CreationMode.NO_CREATE;
+  android.hardware.security.see.storage.FileMode accessMode = android.hardware.security.see.storage.FileMode.READ_WRITE;
+  boolean truncateOnOpen;
 }
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/FileAvailability.aidl b/security/see/storage/aidl/android/hardware/security/see/storage/Availability.aidl
similarity index 95%
rename from staging/security/see/storage/aidl/android/hardware/security/see/storage/FileAvailability.aidl
rename to security/see/storage/aidl/android/hardware/security/see/storage/Availability.aidl
index d339170..e2954d5 100644
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/FileAvailability.aidl
+++ b/security/see/storage/aidl/android/hardware/security/see/storage/Availability.aidl
@@ -16,7 +16,8 @@
 package android.hardware.security.see.storage;
 
 /** Determines how early during the boot process file is able to be accessed. */
-enum FileAvailability {
+@VintfStability
+enum Availability {
     /** Available before userdata is mounted, but after android has booted. */
     BEFORE_USERDATA,
 
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/CreationMode.aidl b/security/see/storage/aidl/android/hardware/security/see/storage/CreationMode.aidl
similarity index 98%
rename from staging/security/see/storage/aidl/android/hardware/security/see/storage/CreationMode.aidl
rename to security/see/storage/aidl/android/hardware/security/see/storage/CreationMode.aidl
index 1c65038..652d5c6 100644
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/CreationMode.aidl
+++ b/security/see/storage/aidl/android/hardware/security/see/storage/CreationMode.aidl
@@ -15,6 +15,7 @@
  */
 package android.hardware.security.see.storage;
 
+@VintfStability
 enum CreationMode {
     /** Returns an error if the file does not already exist. */
     NO_CREATE,
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/FileMode.aidl b/security/see/storage/aidl/android/hardware/security/see/storage/FileMode.aidl
similarity index 97%
rename from staging/security/see/storage/aidl/android/hardware/security/see/storage/FileMode.aidl
rename to security/see/storage/aidl/android/hardware/security/see/storage/FileMode.aidl
index 18a2eae..b167a17 100644
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/FileMode.aidl
+++ b/security/see/storage/aidl/android/hardware/security/see/storage/FileMode.aidl
@@ -15,6 +15,7 @@
  */
 package android.hardware.security.see.storage;
 
+@VintfStability
 enum FileMode {
     /** The file may only be read from. */
     READ_ONLY,
diff --git a/security/see/storage/aidl/android/hardware/security/see/storage/Filesystem.aidl b/security/see/storage/aidl/android/hardware/security/see/storage/Filesystem.aidl
new file mode 100644
index 0000000..eacd4fe
--- /dev/null
+++ b/security/see/storage/aidl/android/hardware/security/see/storage/Filesystem.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.security.see.storage;
+
+import android.hardware.security.see.storage.Availability;
+import android.hardware.security.see.storage.Integrity;
+
+/**
+ * Specifies minimum security requirements for a Secure Storage filesystem.
+ */
+@VintfStability
+parcelable Filesystem {
+    Integrity integrity = Integrity.TAMPER_PROOF_AT_REST;
+    Availability availability = Availability.BEFORE_USERDATA;
+
+    /**
+     * Whether the file is reset on factory resets. Factory resets will not be reported as
+     * tampering.
+     */
+    boolean persistent;
+}
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/IDir.aidl b/security/see/storage/aidl/android/hardware/security/see/storage/IDir.aidl
similarity index 89%
rename from staging/security/see/storage/aidl/android/hardware/security/see/storage/IDir.aidl
rename to security/see/storage/aidl/android/hardware/security/see/storage/IDir.aidl
index a0a9f3d..ddf8ed1 100644
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/IDir.aidl
+++ b/security/see/storage/aidl/android/hardware/security/see/storage/IDir.aidl
@@ -16,6 +16,7 @@
 package android.hardware.security.see.storage;
 
 /** The interface for an open directory */
+@VintfStability
 interface IDir {
     /**
      * Gets the next batch of filenames in this directory.
@@ -26,15 +27,15 @@
      *
      * @maxCount:
      *     the maximum number of filenames to return. A @maxCount of 0 signifies no limit on the
-     * number of filenames returned.
+     *     number of filenames returned.
      *
      * Returns:
      *     An ordered list of filenames. If @maxCount > 0, the length of the returned list will be
-     * less than or equal to @maxCount.
+     *     less than or equal to @maxCount.
      *
      * May return service-specific errors:
-     *   - ERR_FS_* if the filesystem has been tampered with in a way that the `readIntegrity` the
-     *       dir was opened with does not acknowledge
+     *   - ERR_FS_* if the filesystem has been tampered with in a way that the session did not
+     *       acknowledge
      */
     @utf8InCpp String[] readNextFilenames(int maxCount);
 }
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/IFile.aidl b/security/see/storage/aidl/android/hardware/security/see/storage/IFile.aidl
similarity index 86%
rename from staging/security/see/storage/aidl/android/hardware/security/see/storage/IFile.aidl
rename to security/see/storage/aidl/android/hardware/security/see/storage/IFile.aidl
index ff26aa4..414d423 100644
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/IFile.aidl
+++ b/security/see/storage/aidl/android/hardware/security/see/storage/IFile.aidl
@@ -18,6 +18,7 @@
 import android.hardware.security.see.storage.CreationMode;
 
 /** The interface for an open file */
+@VintfStability
 interface IFile {
     /**
      * Read bytes from this file.
@@ -32,8 +33,8 @@
      *     the sequence of bytes at [offset, offset + size) in the file
      *
      * May return service-specific errors:
-     *   - ERR_FS_* if the filesystem has been tampered with in a way that the `readIntegrity` the
-     *       file was opened with does not acknowledge
+     *   - ERR_FS_* if the filesystem has been tampered with in a way that the session did not
+     *       acknowledge
      */
     byte[] read(long size, long offset);
 
@@ -47,8 +48,8 @@
      *     the number of bytes written successfully
      *
      * May return service-specific errors:
-     *   - ERR_FS_* if the filesystem has been tampered with in a way that the `readIntegrity` the
-     *       file was opened with does not acknowledge
+     *   - ERR_FS_* if the filesystem has been tampered with in a way that the session did not
+     *       acknowledge
      */
     long write(long offset, in byte[] buffer);
 
@@ -56,8 +57,8 @@
      * Reads this file's size.
      *
      * May return service-specific errors:
-     *   - ERR_FS_* if the filesystem has been tampered with in a way that the `readIntegrity` the
-     *       file was opened with does not acknowledge
+     *   - ERR_FS_* if the filesystem has been tampered with in a way that the session did not
+     *       acknowledge
      */
     long getSize();
 
@@ -71,8 +72,8 @@
      *     the file's new size
      *
      * May return service-specific errors:
-     *   - ERR_FS_* if the filesystem has been tampered with in a way that the `readIntegrity` the
-     *       file was opened with does not acknowledge
+     *   - ERR_FS_* if the filesystem has been tampered with in a way that the session did not
+     *       acknowledge
      */
     void setSize(long newSize);
 
@@ -88,8 +89,8 @@
      *   - ERR_NOT_FOUND if no file exists at @destPath and @destCreateMode is `NO_CREATE`
      *   - ERR_ALREADY_EXISTS if a file already exists at @destPath and @destCreateMode is
      *       `CREATE_EXCLUSIVE`
-     *   - ERR_FS_* if the filesystem has been tampered with in a way that the `readIntegrity` the
-     *       file was opened with does not acknowledge
+     *   - ERR_FS_* if the filesystem has been tampered with in a way that the session did not
+     *       acknowledge
      */
     void rename(in @utf8InCpp String destPath, in CreationMode destCreateMode);
 }
diff --git a/security/see/storage/aidl/android/hardware/security/see/storage/ISecureStorage.aidl b/security/see/storage/aidl/android/hardware/security/see/storage/ISecureStorage.aidl
new file mode 100644
index 0000000..d2ac4d3
--- /dev/null
+++ b/security/see/storage/aidl/android/hardware/security/see/storage/ISecureStorage.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.security.see.storage;
+
+import android.hardware.security.see.storage.Filesystem;
+import android.hardware.security.see.storage.IStorageSession;
+
+/**
+ * Interface for the Secure Storage HAL
+ *
+ * Creates sessions which can be used to access storage.
+ */
+@VintfStability
+interface ISecureStorage {
+    const int ERR_UNSUPPORTED_PROPERTIES = 1;
+    const int ERR_NOT_FOUND = 2;
+    const int ERR_ALREADY_EXISTS = 3;
+    const int ERR_BAD_TRANSACTION = 4;
+    const int ERR_AB_UPDATE_IN_PROGRESS = 5;
+    const int ERR_FS_TAMPERED = 6;
+
+    /**
+     * Starts a storage session for a filesystem.
+     *
+     * Clients should be prepared for `startSession` and any methods called on the `IStorageSession`
+     * or its sub-interfaces to return `WOULD_BLOCK` (a `binder::Status` with an exception code of
+     * `EX_TRANSACTION_FAILED` and a transaction error code of `android::WOULD_BLOCK`), which
+     * indicates that the requested storage is not currently available. Possible cases that might
+     * cause this return code might be accessing the data partition during boot stages where it
+     * isn't yet mounted or attempting to commit changes while an A/B update is in progress.
+     *
+     * @filesystem:
+     *     The minimum filesystem properties requested.
+     *
+     * May return service-specific errors:
+     *   - ERR_UNSUPPORTED_PROPERTIES if no filesystems exist which meet the minimum requested
+     *       requirements
+     */
+    IStorageSession startSession(in Filesystem filesystem);
+}
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/IStorageSession.aidl b/security/see/storage/aidl/android/hardware/security/see/storage/IStorageSession.aidl
similarity index 73%
rename from staging/security/see/storage/aidl/android/hardware/security/see/storage/IStorageSession.aidl
rename to security/see/storage/aidl/android/hardware/security/see/storage/IStorageSession.aidl
index cd126b8..b5762aa 100644
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/IStorageSession.aidl
+++ b/security/see/storage/aidl/android/hardware/security/see/storage/IStorageSession.aidl
@@ -15,12 +15,10 @@
  */
 package android.hardware.security.see.storage;
 
-import android.hardware.security.see.storage.DeleteOptions;
+import android.hardware.security.see.storage.CreationMode;
 import android.hardware.security.see.storage.IDir;
 import android.hardware.security.see.storage.IFile;
 import android.hardware.security.see.storage.OpenOptions;
-import android.hardware.security.see.storage.ReadIntegrity;
-import android.hardware.security.see.storage.RenameOptions;
 
 /**
  * Interface for a Secure Storage session
@@ -33,6 +31,7 @@
  *
  * Any changes still pending when the session is dropped will be abandoned.
  */
+@VintfStability
 interface IStorageSession {
     /**
      * Commits any pending changes made through this session to storage.
@@ -46,6 +45,21 @@
     void commitChanges();
 
     /**
+     * If an A/B update is in progress, stages any pending changes made through this session to be
+     * committed when the A/B update completes successfully. If the update fails, the changes will
+     * be discarded.
+     *
+     * If no A/B update is in progess, behaves identically to `commitChanges`.
+     *
+     * After this call returns successfully, the session will no longer have pending changes. Files
+     * may then still be modified through this session to create another commit.
+     *
+     * May return service-specific errors:
+     *   - ERR_BAD_TRANSACTION
+     */
+    void stageChangesForCommitOnAbUpdateComplete();
+
+    /**
      * Abandons any pending changes made through this session.
      *
      * The session can then be reused to make new changes.
@@ -66,8 +80,8 @@
      * May return service-specific errors:
      *   - ERR_NOT_FOUND
      *   - ERR_ALREADY_EXISTS
-     *   - ERR_FS_* if the filesystem has been tampered with in a way that @options.readIntegrity
-     *       does not acknowledge
+     *   - ERR_FS_* if the filesystem has been tampered with in a way that the session did not
+     *       acknowledge
      */
     IFile openFile(in @utf8InCpp String filePath, in OpenOptions options);
 
@@ -81,33 +95,34 @@
      *
      * May return service-specific errors:
      *   - ERR_NOT_FOUND
-     *   - ERR_FS_* if the filesystem has been tampered with in a way that @options.readIntegrity
-     *       does not acknowledge
+     *   - ERR_FS_* if the filesystem has been tampered with in a way that the session did not
+     *       acknowledge
      */
-    void deleteFile(in @utf8InCpp String filePath, in DeleteOptions options);
+    void deleteFile(in @utf8InCpp String filePath);
 
     /**
      * Renames an existing file.
      *
-     * The file must not already be opened. (If it is, use `IFile::rename`.)
+     * Will return `ILLEGAL_STATE` if the file is already opened. In that case, use `IFile::rename`
+     * instead.
      *
      * @currentPath:
      *     path to the file, relative to filesystem root
      * @destPath:
      *     the file's new path, relative to filesystem root
-     * @options:
-     *     options controlling rename behavior
+     * @destCreateMode:
+     *     creation behavior for the dest file
      *
      * May return service-specific errors:
-     *   - ERR_NOT_FOUND if no file exists at @currentPath, or if @options.destCreateMode is
-     *       `NO_CREATE` and no file exists at @destPath
-     *   - ERR_ALREADY_EXISTS if @options.destCreateMode is `CREATE_EXCLUSIVE` and a file exists at
+     *   - ERR_NOT_FOUND if no file exists at @currentPath, or if @destCreateMode is `NO_CREATE` and
+     *       no file exists at @destPath
+     *   - ERR_ALREADY_EXISTS if @destCreateMode is `CREATE_EXCLUSIVE` and a file exists at
      *       @destPath
-     *   - ERR_FS_* if the filesystem has been tampered with in a way that @options.readIntegrity
-     *       does not acknowledge
+     *   - ERR_FS_* if the filesystem has been tampered with in a way that the session did not
+     *       acknowledge
      */
     void renameFile(in @utf8InCpp String currentPath, in @utf8InCpp String destPath,
-            in RenameOptions options);
+            in CreationMode destCreateMode);
 
     /**
      * Opens a directory from a filesystem with the given properties.
@@ -116,14 +131,11 @@
      *
      * @path:
      *     path to the directory, relative to filesystem root
-     * @readIntegrity:
-     *     allow opening (and subsequent read/write operations) despite possible tampering for the
-     * directory
      *
      * May return service-specific errors:
      *   - ERR_NOT_FOUND
-     *   - ERR_FS_* if the filesystem has been tampered with in a way that @readIntegrity does not
+     *   - ERR_FS_* if the filesystem has been tampered with in a way that the session did not
      *       acknowledge
      */
-    IDir openDir(in @utf8InCpp String path, in ReadIntegrity readIntegrity);
+    IDir openDir(in @utf8InCpp String path);
 }
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/FileIntegrity.aidl b/security/see/storage/aidl/android/hardware/security/see/storage/Integrity.aidl
similarity index 82%
rename from staging/security/see/storage/aidl/android/hardware/security/see/storage/FileIntegrity.aidl
rename to security/see/storage/aidl/android/hardware/security/see/storage/Integrity.aidl
index 1879b16..6f86ab0 100644
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/FileIntegrity.aidl
+++ b/security/see/storage/aidl/android/hardware/security/see/storage/Integrity.aidl
@@ -15,7 +15,8 @@
  */
 package android.hardware.security.see.storage;
 
-enum FileIntegrity {
+@VintfStability
+enum Integrity {
     /** REE may prevent operations, but cannot alter data once written. */
     TAMPER_PROOF_AT_REST,
 
@@ -24,10 +25,4 @@
      * an error on read.
      */
     TAMPER_DETECT,
-
-    /**
-     * REE may alter written data. Changes other than full filesystem resets will be detected and
-     * reported.
-     */
-    TAMPER_DETECT_IGNORE_RESET,
 }
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/OpenOptions.aidl b/security/see/storage/aidl/android/hardware/security/see/storage/OpenOptions.aidl
similarity index 65%
rename from staging/security/see/storage/aidl/android/hardware/security/see/storage/OpenOptions.aidl
rename to security/see/storage/aidl/android/hardware/security/see/storage/OpenOptions.aidl
index 997ca62..110b370 100644
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/OpenOptions.aidl
+++ b/security/see/storage/aidl/android/hardware/security/see/storage/OpenOptions.aidl
@@ -17,8 +17,8 @@
 
 import android.hardware.security.see.storage.CreationMode;
 import android.hardware.security.see.storage.FileMode;
-import android.hardware.security.see.storage.ReadIntegrity;
 
+@VintfStability
 parcelable OpenOptions {
     /** Controls creation behavior of the to-be-opened file. See `CreationMode` docs for details. */
     CreationMode createMode = CreationMode.NO_CREATE;
@@ -27,25 +27,8 @@
     FileMode accessMode = FileMode.READ_WRITE;
 
     /**
-     * Set to acknowledge possible files tampering.
-     *
-     * If unacknowledged tampering is detected, the operation will fail with an ERR_FS_*
-     * service-specific code.
-     */
-    ReadIntegrity readIntegrity = ReadIntegrity.NO_TAMPER;
-
-    /**
      * If this file already exists, discard existing content and open
      * it as a new file. No semantic change if the file does not exist.
      */
     boolean truncateOnOpen;
-
-    /**
-     * Allow writes to succeed while the filesystem is in the middle of an A/B update.
-     *
-     * If the A/B update fails, the operation will be rolled back. This rollback will not
-     * cause subsequent operations fail with any ERR_FS_* code nor will need to be
-     * acknowledged by setting the `readIntegrity`.
-     */
-    boolean allowWritesDuringAbUpdate = false;
 }
diff --git a/security/sharedsecret/aidl/Android.bp b/security/sharedsecret/aidl/Android.bp
index fe77c10..adf33d3 100644
--- a/security/sharedsecret/aidl/Android.bp
+++ b/security/sharedsecret/aidl/Android.bp
@@ -10,6 +10,7 @@
 aidl_interface {
     name: "android.hardware.security.sharedsecret",
     vendor_available: true,
+    frozen: true,
     srcs: [
         "android/hardware/security/sharedsecret/*.aidl",
     ],
diff --git a/security/sharedsecret/aidl/vts/functional/Android.bp b/security/sharedsecret/aidl/vts/functional/Android.bp
index 1f0f6a6..eedd325 100644
--- a/security/sharedsecret/aidl/vts/functional/Android.bp
+++ b/security/sharedsecret/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index d53179a..b042907 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_sensors",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
index 62eaf6b..a62a0e7 100644
--- a/sensors/2.0/vts/functional/Android.bp
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_sensors",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/sensors/2.1/vts/functional/Android.bp b/sensors/2.1/vts/functional/Android.bp
index 61cfd14..e8777e5 100644
--- a/sensors/2.1/vts/functional/Android.bp
+++ b/sensors/2.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_sensors",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/sensors/aidl/android/hardware/sensors/SensorType.aidl b/sensors/aidl/android/hardware/sensors/SensorType.aidl
index 9098894..4904c3f 100644
--- a/sensors/aidl/android/hardware/sensors/SensorType.aidl
+++ b/sensors/aidl/android/hardware/sensors/SensorType.aidl
@@ -718,8 +718,8 @@
     HEADING = 42,
 
     /**
-     * Base for device manufacturers private sensor types.
-     * These sensor types can't be exposed in the SDK.
+     * Base of the range reserved for device manufacturers' private sensor
+     * types. These sensor types aren't documented in the SDK.
      */
     DEVICE_PRIVATE_BASE = 0x10000,
 }
diff --git a/sensors/aidl/default/include/sensors-impl/Sensors.h b/sensors/aidl/default/include/sensors-impl/Sensors.h
index 2adbc9d..c90db69 100644
--- a/sensors/aidl/default/include/sensors-impl/Sensors.h
+++ b/sensors/aidl/default/include/sensors-impl/Sensors.h
@@ -97,9 +97,13 @@
             return;
         }
         if (mEventQueue->write(&events.front(), events.size())) {
+            if (mEventQueueFlag == nullptr) {
+                // Don't take the wake lock if we can't wake the receiver to avoid holding it
+                // indefinitely.
+                return;
+            }
             mEventQueueFlag->wake(
                     static_cast<uint32_t>(BnSensors::EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS));
-
             if (wakeup) {
                 // Keep track of the number of outstanding WAKE_UP events in order to properly hold
                 // a wake lock until the framework has secured a wake lock
diff --git a/soundtrigger/2.0/default/Android.bp b/soundtrigger/2.0/default/Android.bp
index 2cbf041..2e61f9b 100644
--- a/soundtrigger/2.0/default/Android.bp
+++ b/soundtrigger/2.0/default/Android.bp
@@ -46,3 +46,36 @@
         "libhardware_headers",
     ],
 }
+
+soong_config_module_type {
+    name: "soundtrigger_cc_library_shared",
+    module_type: "cc_library_shared",
+    config_namespace: "soundtrigger",
+    value_variables: [
+        "audioserver_multilib",
+    ],
+    properties: ["compile_multilib"],
+}
+
+soundtrigger_cc_library_shared {
+    name: "android.hardware.soundtrigger@2.0-impl",
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: ["FetchISoundTriggerHw.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libhardware",
+        "libutils",
+        "android.hardware.soundtrigger@2.0",
+        "android.hardware.soundtrigger@2.0-core",
+    ],
+    compile_multilib: "32",
+    soong_config_variables: {
+        audioserver_multilib: {
+            compile_multilib: "%s",
+        },
+    },
+}
diff --git a/soundtrigger/2.0/default/Android.mk b/soundtrigger/2.0/default/Android.mk
deleted file mode 100644
index 17e4440..0000000
--- a/soundtrigger/2.0/default/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Copyright (C) 2016 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.
-
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.soundtrigger@2.0-impl
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := \
-    FetchISoundTriggerHw.cpp
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
-        libhardware \
-        libutils \
-        android.hardware.soundtrigger@2.0 \
-        android.hardware.soundtrigger@2.0-core
-
-LOCAL_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
-LOCAL_MULTILIB := 32
-else
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/soundtrigger/2.0/vts/functional/Android.bp b/soundtrigger/2.0/vts/functional/Android.bp
index 403fa9b..dde1aa1 100644
--- a/soundtrigger/2.0/vts/functional/Android.bp
+++ b/soundtrigger/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_audio_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/soundtrigger/2.1/default/Android.bp b/soundtrigger/2.1/default/Android.bp
new file mode 100644
index 0000000..a246680
--- /dev/null
+++ b/soundtrigger/2.1/default/Android.bp
@@ -0,0 +1,57 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: [
+        "hardware_interfaces_license",
+    ],
+}
+
+soong_config_module_type_import {
+    from: "hardware/interfaces/soundtrigger/2.0/default/Android.bp",
+    module_types: ["soundtrigger_cc_library_shared"],
+}
+
+soundtrigger_cc_library_shared {
+    name: "android.hardware.soundtrigger@2.1-impl",
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: ["SoundTriggerHw.cpp"],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    shared_libs: [
+        "libhardware",
+        "libhidlbase",
+        "libhidlmemory",
+        "liblog",
+        "libutils",
+        "android.hardware.soundtrigger@2.1",
+        "android.hardware.soundtrigger@2.0",
+        "android.hardware.soundtrigger@2.0-core",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+    ],
+    compile_multilib: "32",
+    soong_config_variables: {
+        audioserver_multilib: {
+            compile_multilib: "%s",
+        },
+    },
+}
diff --git a/soundtrigger/2.1/default/Android.mk b/soundtrigger/2.1/default/Android.mk
deleted file mode 100644
index 602f5a7..0000000
--- a/soundtrigger/2.1/default/Android.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# Copyright (C) 2018 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.
-
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.soundtrigger@2.1-impl
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := \
-    SoundTriggerHw.cpp
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
-        libhardware \
-        libhidlbase \
-        libhidlmemory \
-        liblog \
-        libutils \
-        android.hardware.soundtrigger@2.1 \
-        android.hardware.soundtrigger@2.0 \
-        android.hardware.soundtrigger@2.0-core \
-        android.hidl.allocator@1.0 \
-        android.hidl.memory@1.0
-
-LOCAL_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
-LOCAL_MULTILIB := 32
-else
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/soundtrigger/2.1/vts/functional/Android.bp b/soundtrigger/2.1/vts/functional/Android.bp
index b013350..3e475e6 100644
--- a/soundtrigger/2.1/vts/functional/Android.bp
+++ b/soundtrigger/2.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_audio_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/soundtrigger/2.2/vts/functional/Android.bp b/soundtrigger/2.2/vts/functional/Android.bp
index faf6d58..3502545 100644
--- a/soundtrigger/2.2/vts/functional/Android.bp
+++ b/soundtrigger/2.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_audio_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/soundtrigger/2.3/vts/functional/Android.bp b/soundtrigger/2.3/vts/functional/Android.bp
index e613db5..23cbe85 100644
--- a/soundtrigger/2.3/vts/functional/Android.bp
+++ b/soundtrigger/2.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_audio_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/staging/security/see/Android.bp b/staging/security/see/Android.bp
new file mode 100644
index 0000000..a83b65d
--- /dev/null
+++ b/staging/security/see/Android.bp
@@ -0,0 +1,5 @@
+dirgroup {
+    name: "trusty_dirgroup_hardware_interfaces_staging_security_see",
+    dirs: ["."],
+    visibility: ["//trusty/vendor/google/aosp/scripts"],
+}
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl b/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
deleted file mode 100644
index b5e7e9d..0000000
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.hardware.security.see.hwcrypto;
-
-import android.hardware.security.see.hwcrypto.IHwCryptoOperations;
-import android.hardware.security.see.hwcrypto.IOpaqueKey;
-import android.hardware.security.see.hwcrypto.KeyPolicy;
-import android.hardware.security.see.hwcrypto.types.ExplicitKeyMaterial;
-
-/*
- * Higher level interface to access and generate keys.
- */
-interface IHwCryptoKey {
-    /*
-     * Identifier for the requested device provided key. The currently supported identifiers are:
-     *
-     * DEVICE_BOUND_KEY:
-     *      This is a key unique to the device.
-     * BATCH_KEY:
-     *      This is a shared by a set of devices.
-     */
-    enum DeviceKeyId {
-        DEVICE_BOUND_KEY,
-        BATCH_KEY,
-    }
-    union DiceBoundDerivationKey {
-        /*
-         * Opaque to be used to derive the DICE bound key.
-         */
-        IOpaqueKey opaqueKey;
-
-        /*
-         * Device provided key to be used to derive the DICE bound key.
-         */
-        DeviceKeyId keyId;
-    }
-
-    parcelable DiceCurrentBoundKeyResult {
-        /*
-         * Key cryptographically bound to a DICE policy.
-         */
-        IOpaqueKey diceBoundKey;
-
-        /*
-         * Current dice policy which was used to generate the returned key. This policy is
-         * opaque from this service perspective (it will be sent to an Authentication Manager
-         * Service to be verified). It follows the structure defined on DicePolicy.cddl, located
-         * under hardware/interfaces/security/authgraph/aidl/android/hardware/security/authgraph/
-         * with the caveat that it could be encrypted if the client does not have enough permissions
-         * to see the device dice policy information.
-         */
-        byte[] dicePolicyForKeyVersion;
-    }
-
-    parcelable DiceBoundKeyResult {
-        /*
-         * Key cryptographically bound to a DICE policy.
-         */
-        IOpaqueKey diceBoundKey;
-
-        /*
-         * Indicates if the diceBoundKey returned was created using a current DICE policy. The
-         * caller can use this to detect if an old policy was provided and rotate its keys if so
-         * desired. Old, valid policies remain usable, but care needs to be taken to not continue to
-         * use a potentially compromised key.
-         */
-        boolean dicePolicyWasCurrent;
-    }
-
-    parcelable ClearKeyPolicy {
-        /*
-         * Indicates the desired key size. It will be used to calculate how many bytes of key
-         * material should be returned.
-         */
-        int keySizeBytes;
-    }
-
-    union DerivedKeyPolicy {
-        /*
-         * If used we will derive a clear key and pass it back as an array of bytes on
-         * <code>HwCryptoKeyMaterial::explicitKey</code>.
-         */
-        ClearKeyPolicy clearKey;
-
-        /*
-         * Policy for the newly derived opaque key. Defines how the key can be used and its type.
-         */
-        byte[] opaqueKey;
-    }
-
-    parcelable DerivedKeyParameters {
-        /*
-         * Key to be used to derive the new key using HKDF.
-         */
-        IOpaqueKey derivationKey;
-
-        /*
-         * Policy for the newly derived key. Depending on its type, either a clear or opaque key
-         * will be derived.
-         */
-        DerivedKeyPolicy keyPolicy;
-
-        /*
-         * An arbitrary set of bytes incorporated into the key derivation. May have
-         * an implementation-specific maximum length, but it is guaranteed to accept
-         * at least 32 bytes.
-         */
-        byte[] context;
-    }
-
-    union DerivedKey {
-        /*
-         * Derived key in clear format.
-         */
-        byte[] explicitKey = {};
-
-        /*
-         * Derived key as a key token to be used only through the HWCrypto service.
-         */
-        IOpaqueKey opaque;
-    }
-
-    /*
-     * deriveCurrentDicePolicyBoundKey() - Derives a versioned key tied to the caller's current DICE
-     *                              policy. It will return this current policy back to the caller
-     *                              along with the generated key.
-     *
-     * @derivationKey:
-     *     Key to be used to derive the new key using HKDF.
-     *
-     * Return:
-     *      Ok(DiceCurrentBoundKeyResult) on success, service specific error based on
-     *      <code>HalErrorCode</code> otherwise.
-     */
-    DiceCurrentBoundKeyResult deriveCurrentDicePolicyBoundKey(
-            in DiceBoundDerivationKey derivationKey);
-
-    /*
-     * deriveDicePolicyBoundKey() - Derive a versioned key by checking the provided DICE policy
-     *                              against the caller and then using it as a context for deriving
-     *                              the returned key.
-     *
-     * @derivationKey:
-     *     Key to be used to derive the new key using HKDF.
-     *
-     * @dicePolicyForKeyVersion:
-     *     Policy used to derive keys tied to specific versions. Using this parameter
-     *     the caller can tie a derived key to a minimum version of itself, so in the future only
-     *     itself or a more recent version can derive the same key. This parameter is opaque to the
-     *     caller and it could be encrypted in the case the client doesn't have permission to know
-     *     the dice chain.
-     *     When implementing this function, this parameter shall be one of the components fed
-     *     to the KDF context and it needs to be checked against the caller DICE certificate before
-     *     being used.
-     *
-     * Return:
-     *      Ok(DiceBoundKeyResult) on success, service specific error based on
-     *      <code>HalErrorCode</code> otherwise.
-     */
-    DiceBoundKeyResult deriveDicePolicyBoundKey(
-            in DiceBoundDerivationKey derivationKey, in byte[] dicePolicyForKeyVersion);
-
-    /*
-     * deriveKey() - Derive a new key based on the given key, policy and context.
-     *
-     * @parameters:
-     *      Parameters used for the key derivation. See <code>DerivedKeyParameters</code> on this
-     *      file for more information.
-     *
-     * Return:
-     *      Ok(HwCryptoKeyMaterial) on success, service specific error based on
-     *      <code>HalErrorCode</code> otherwise.
-     */
-    DerivedKey deriveKey(in DerivedKeyParameters parameters);
-
-    /*
-     * getHwCryptoOperations() - Returns an interface used to work on opaque keys. This interface
-     *                           can also be used to operate on any opaque key generated by
-     *                           hwkeyDeriveVersioned, even if this key has been generated after
-     *                           retrieving a IHwCryptoOperations binder object, as long as the
-     *                           parent IHwCryptoDeviceKeyAccess is not dropped between retrieving
-     *                           the IHwCryptoOperations binder object and deriving the key.
-     *                           IHwCryptoOperations can also be used to create opaque keys that
-     *                           are not bound to the device.
-     *
-     * Return:
-     *      IHwCryptoOperations on success
-     */
-    IHwCryptoOperations getHwCryptoOperations();
-
-    /*
-     * importClearKey() - Imports a SW clear key into the secure environment.
-     *
-     * @keyMaterial:
-     *     key to be imported.
-     * @newKeyPolicy:
-     *      Policy of the new key. Defines how the newly created key can be used. Because any
-     *      clear key imported into the system is considered to have a
-     *      <code>KeyLifetime::PORTABLE</code> lifetime, a call to this function will return an
-     *      error if <code>newKeyPolicy.newKeyPolicy</code> is not set to portable.
-     *
-     * Return:
-     *      IOpaqueKey on success, service specific error based on <code>HalErrorCode</code>
-     *      otherwise.
-     */
-    IOpaqueKey importClearKey(in ExplicitKeyMaterial keyMaterial, in KeyPolicy newKeyPolicy);
-}
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IOpaqueKey.aidl b/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IOpaqueKey.aidl
deleted file mode 100644
index 0d0f613..0000000
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IOpaqueKey.aidl
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.hardware.security.see.hwcrypto;
-
-import android.hardware.security.see.hwcrypto.KeyPolicy;
-import android.hardware.security.see.hwcrypto.types.OperationType;
-
-interface IOpaqueKey {
-    /*
-     * exportWrappedKey() - Exports this key as a wrapped (encrypted) blob.
-     *
-     * @wrapping_key:
-     *     wrapping key. It needs to be an opaque key and its policy needs to indicate that it can
-     *     be used for key wrapping.
-     *
-     * Return:
-     *      Wrapped key blob as a byte array on success. Format of the blob is opaque to the service
-     *      but has to match the command accepted by
-     *      <code>IHwCryptoKeyGeneration::importWrappedKey</code>, service specific error based on
-     *      <code>HalErrorCode</code> otherwise.
-     */
-    byte[] exportWrappedKey(in IOpaqueKey wrappingKey);
-
-    /*
-     * getKeyPolicy() - Returns the key policy.
-     *
-     * Return:
-     *      A <code>KeyPolicy</code> on success, service specific error based on
-     *      <code>HalErrorCode</code> otherwise.
-     */
-    KeyPolicy getKeyPolicy();
-
-    /*
-     * getPublicKey() - Returns the public key portion of this OpaqueKey. This operation is only
-     *                  valid for asymmetric keys
-     *
-     * Return:
-     *      public key as a byte array on success, service specific error based on
-     *      <code>HalErrorCode</code> otherwise. Format used for the returned public key is COSE.
-     */
-    byte[] getPublicKey();
-}
diff --git a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyType.aidl b/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyType.aidl
deleted file mode 100644
index 3cf4670..0000000
--- a/staging/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/types/KeyType.aidl
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.hardware.security.see.hwcrypto.types;
-
-/*
- * Enum describing all supported key types. Key types are strongly bound to the algorithm to
- * prevent reusing the same key on different algorithms (e.g. using the same key for 2 different AES
- * 128 Cipher modes).
- */
-enum KeyType {
-    AES_128_CBC_NO_PADDING,
-    AES_128_CBC_PKCS7_PADDING,
-    AES_128_CTR,
-    AES_128_GCM,
-    AES_128_CMAC,
-    AES_256_CBC_NO_PADDING,
-    AES_256_CBC_PKCS7_PADDING,
-    AES_256_CTR,
-    AES_256_GCM,
-    AES_256_CMAC,
-    HMAC_SHA256,
-    HMAC_SHA512,
-    RSA2048_PSS_SHA256,
-    RSA2048_PKCS1_5_SHA256,
-    ECC_NIST_P256_SIGN_NO_PADDING,
-    ECC_NIST_P256_SIGN_SHA256,
-    ECC_NIST_P521_SIGN_NO_PADDING,
-    ECC_NIST_P521_SIGN_SHA512,
-    ECC_ED25519_SIGN,
-}
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/DeleteOptions.aidl b/staging/security/see/storage/aidl/android/hardware/security/see/storage/DeleteOptions.aidl
deleted file mode 100644
index 1a94eb2..0000000
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/DeleteOptions.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.hardware.security.see.storage;
-
-import android.hardware.security.see.storage.ReadIntegrity;
-
-parcelable DeleteOptions {
-    /**
-     * Set to acknowledge possible files tampering.
-     *
-     * If unacknowledged tampering is detected, the operation will fail with an ERR_FS_*
-     * service-specific code.
-     */
-    ReadIntegrity readIntegrity = ReadIntegrity.NO_TAMPER;
-
-    /**
-     * Allow writes to succeed while the filesystem is in the middle of an A/B update.
-     *
-     * If the A/B update fails, the operation will be rolled back. This rollback will not
-     * cause subsequent operations fail with any ERR_FS_* code nor will need to be
-     * acknowledged by setting the `readIntegrity`.
-     */
-    boolean allowWritesDuringAbUpdate = false;
-}
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/FileProperties.aidl b/staging/security/see/storage/aidl/android/hardware/security/see/storage/FileProperties.aidl
deleted file mode 100644
index 733b5b0..0000000
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/FileProperties.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.hardware.security.see.storage;
-
-import android.hardware.security.see.storage.FileAvailability;
-import android.hardware.security.see.storage.FileIntegrity;
-
-parcelable FileProperties {
-    FileIntegrity integrity = FileIntegrity.TAMPER_PROOF_AT_REST;
-    FileAvailability availability = FileAvailability.BEFORE_USERDATA;
-
-    /** Whether the file is reset when user data is wiped. */
-    boolean persistent;
-}
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/ISecureStorage.aidl b/staging/security/see/storage/aidl/android/hardware/security/see/storage/ISecureStorage.aidl
deleted file mode 100644
index be3c045..0000000
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/ISecureStorage.aidl
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.hardware.security.see.storage;
-
-import android.hardware.security.see.storage.FileProperties;
-import android.hardware.security.see.storage.IStorageSession;
-
-/**
- * Interface for the Secure Storage HAL
- *
- * Creates sessions which can be used to access storage.
- */
-interface ISecureStorage {
-    const int ERR_UNSUPPORTED_PROPERTIES = 1;
-    const int ERR_NOT_FOUND = 2;
-    const int ERR_ALREADY_EXISTS = 3;
-    const int ERR_BAD_TRANSACTION = 4;
-
-    const int ERR_FS_RESET = 5;
-    const int ERR_FS_ROLLED_BACK = 6;
-    const int ERR_FS_TAMPERED = 7;
-
-    /**
-     * Starts a storage session for a filesystem.
-     *
-     * @properties:
-     *     the minimum filesystem properties requested for the session.
-     *
-     * May return service-specific errors:
-     *   - ERR_UNSUPPORTED_PROPERTIES if no filesystems exist which meet the minimum requested
-     * requirements
-     */
-    IStorageSession startSession(in FileProperties properties);
-}
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/ReadIntegrity.aidl b/staging/security/see/storage/aidl/android/hardware/security/see/storage/ReadIntegrity.aidl
deleted file mode 100644
index cc0e4f9..0000000
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/ReadIntegrity.aidl
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.hardware.security.see.storage;
-
-enum ReadIntegrity {
-    /**
-     * Return an error on reads if any REE alteration of the written data
-     * has been detected.
-     */
-    NO_TAMPER,
-
-    /**
-     * Return an error on reads if any REE alteration other than a reset
-     * has been detected.
-     */
-    IGNORE_RESET,
-
-    /**
-     * Return an error if any REE alteration other than a rollback to a
-     * valid checkpoint has been detected. (What makes a checkpoint valid is
-     * implementation defined; an implementation might take a checkpoint on its
-     * first post-factory boot. A reset is a rollback to the initial state.)
-     */
-    IGNORE_ROLLBACK,
-
-    // There's no `IGNORE_ALL` because if REE has done any alteration other
-    // than a rollback, the file contents will be known-bad data.
-}
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/RenameOptions.aidl b/staging/security/see/storage/aidl/android/hardware/security/see/storage/RenameOptions.aidl
deleted file mode 100644
index f55ea7f..0000000
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/RenameOptions.aidl
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.hardware.security.see.storage;
-
-import android.hardware.security.see.storage.CreationMode;
-import android.hardware.security.see.storage.ReadIntegrity;
-
-parcelable RenameOptions {
-    /** Controls creation behavior of the dest file. See `CreationMode` docs for details. */
-    CreationMode destCreateMode = CreationMode.CREATE_EXCLUSIVE;
-
-    /**
-     * Set to acknowledge possible files tampering.
-     *
-     * If unacknowledged tampering is detected, the operation will fail with an ERR_FS_*
-     * service-specific code.
-     */
-    ReadIntegrity readIntegrity = ReadIntegrity.NO_TAMPER;
-
-    /**
-     * Allow writes to succeed while the filesystem is in the middle of an A/B update.
-     *
-     * If the A/B update fails, the operation will be rolled back. This rollback will not
-     * cause subsequent operations fail with any ERR_FS_* code nor will need to be
-     * acknowledged by setting the `readIntegrity`.
-     */
-    boolean allowWritesDuringAbUpdate = false;
-}
diff --git a/staging/security/see/storage/aidl/android/hardware/security/see/storage/Tamper.aidl b/staging/security/see/storage/aidl/android/hardware/security/see/storage/Tamper.aidl
deleted file mode 100644
index 0a39fdd..0000000
--- a/staging/security/see/storage/aidl/android/hardware/security/see/storage/Tamper.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.hardware.security.see.storage;
-
-/** Specifies types of REE tampering the filesystem may detect */
-enum Tamper {
-    /** REE has reset this file or the containing file system. */
-    RESET,
-
-    /** REE has rolled back this file or the containing file system to a previous state. */
-    ROLLBACK,
-
-    /** REE has made some other modification to the file. */
-    OTHER,
-}
diff --git a/tests/extension/vibrator/aidl/Android.bp b/tests/extension/vibrator/aidl/Android.bp
index 0306dca..3ef8749 100644
--- a/tests/extension/vibrator/aidl/Android.bp
+++ b/tests/extension/vibrator/aidl/Android.bp
@@ -37,6 +37,15 @@
         java: {
             enabled: false,
         },
+        ndk: {
+            enabled: true,
+        },
+        cpp: {
+            enabled: false,
+        },
+        rust: {
+            enabled: false,
+        },
     },
     frozen: true,
     versions_with_info: [
diff --git a/tests/extension/vibrator/aidl/client/Android.bp b/tests/extension/vibrator/aidl/client/Android.bp
index 284ac74..00510b7 100644
--- a/tests/extension/vibrator/aidl/client/Android.bp
+++ b/tests/extension/vibrator/aidl/client/Android.bp
@@ -16,16 +16,10 @@
     srcs: [
         // system code has the option to use the unstable C++ libbinder API
         // or the NDK one. For maximum code portability, using the ndk client
-        // makes the most sense, but both are provided here as an example.
-        "test-cpp-client.cpp",
+        // makes the most sense.
         "test-ndk-client.cpp",
     ],
     shared_libs: [
-        "libbinder",
-        "libutils",
-        "android.hardware.vibrator-V2-cpp",
-        "android.hardware.tests.extension.vibrator-V1-cpp",
-
         "libbinder_ndk",
         "android.hardware.vibrator-V2-ndk",
         "android.hardware.tests.extension.vibrator-V1-ndk",
diff --git a/tests/extension/vibrator/aidl/client/test-cpp-client.cpp b/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
deleted file mode 100644
index 015a345..0000000
--- a/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2019 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 <android/hardware/tests/extension/vibrator/ICustomVibrator.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <binder/IInterface.h>
-#include <binder/IServiceManager.h>
-#include <gtest/gtest.h>
-
-using android::checked_interface_cast;
-using android::IBinder;
-using android::IInterface;
-using android::OK;
-using android::sp;
-using android::waitForVintfService;
-using android::hardware::tests::extension::vibrator::Directionality;
-using android::hardware::tests::extension::vibrator::ICustomVibrator;
-using android::hardware::vibrator::IVibrator;
-
-TEST(Cpp, CallRootMethod) {
-    sp<IVibrator> vib = waitForVintfService<IVibrator>();
-    ASSERT_NE(nullptr, vib.get());
-    ASSERT_TRUE(vib->off().isOk());
-}
-
-TEST(Cpp, CallExtMethod) {
-    // normally you would want to cache this
-    sp<IVibrator> vib = waitForVintfService<IVibrator>();
-    ASSERT_NE(nullptr, vib.get());
-
-    // getting the extension
-    sp<IBinder> ext;
-    ASSERT_EQ(OK, IInterface::asBinder(vib)->getExtension(&ext));
-    sp<ICustomVibrator> cvib = checked_interface_cast<ICustomVibrator>(ext);
-    ASSERT_NE(nullptr, cvib.get());
-
-    // calling extension method
-    ASSERT_TRUE(cvib->setDirectionality(Directionality::TRANSVERSE).isOk());
-}
diff --git a/tests/extension/vibrator/aidl/client/test-ndk-client.cpp b/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
index c846495..4dd86e8 100644
--- a/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
+++ b/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
@@ -28,7 +28,7 @@
 static const std::string kInstance = std::string() + IVibrator::descriptor + "/default";
 
 TEST(Ndk, CallRootMethod) {
-    SpAIBinder vibBinder = SpAIBinder(AServiceManager_getService(kInstance.c_str()));
+    SpAIBinder vibBinder = SpAIBinder(AServiceManager_waitForService(kInstance.c_str()));
     ASSERT_NE(nullptr, vibBinder.get());
     std::shared_ptr<IVibrator> vib = IVibrator::fromBinder(vibBinder);
     ASSERT_NE(nullptr, vib.get());
@@ -38,7 +38,7 @@
 TEST(Ndk, CallExtMethod) {
     // normally you would want to cache this
     //
-    SpAIBinder vibBinder = SpAIBinder(AServiceManager_getService(kInstance.c_str()));
+    SpAIBinder vibBinder = SpAIBinder(AServiceManager_waitForService(kInstance.c_str()));
     ASSERT_NE(nullptr, vibBinder.get());
     std::shared_ptr<IVibrator> vib = IVibrator::fromBinder(vibBinder);
     ASSERT_NE(nullptr, vib.get());
diff --git a/tests/extension/vibrator/aidl/default/Android.bp b/tests/extension/vibrator/aidl/default/Android.bp
index 5e156af..479b4fd 100644
--- a/tests/extension/vibrator/aidl/default/Android.bp
+++ b/tests/extension/vibrator/aidl/default/Android.bp
@@ -10,11 +10,6 @@
 cc_binary {
     name: "android.hardware.tests.extension.vibrator-service.example",
     relative_install_path: "hw",
-    // normally you implement a service directly, but we are using an implementation
-    // from a library to attach our extension to.
-    static_libs: [
-        "libvibratorexampleimpl",
-    ],
 
     // need to add this in the manifest and to init as well to use, see
     // android.hardware.vibrator-service.example. This binary is being tested
@@ -23,6 +18,7 @@
     vendor: true,
     srcs: [
         "service.cpp",
+        "Vibrator.cpp",
         "CustomVibrator.cpp",
     ],
     shared_libs: [
diff --git a/tests/extension/vibrator/aidl/default/Vibrator.cpp b/tests/extension/vibrator/aidl/default/Vibrator.cpp
new file mode 100644
index 0000000..5084096
--- /dev/null
+++ b/tests/extension/vibrator/aidl/default/Vibrator.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2024 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 "Vibrator.h"
+
+#include <android-base/logging.h>
+
+namespace aidl::android::hardware::vibrator {
+
+ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
+    // basic example with only amplitude control capability
+    *_aidl_return = IVibrator::CAP_AMPLITUDE_CONTROL;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::off() {
+    LOG(INFO) << "Vibrator off";
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs, const std::shared_ptr<IVibratorCallback>&) {
+    LOG(INFO) << "Vibrator on for timeoutMs: " << timeoutMs;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
+    LOG(INFO) << "Vibrator set amplitude: " << amplitude;
+    if (amplitude <= 0.0f || amplitude > 1.0f) {
+        return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::perform(Effect, EffectStrength,
+                                     const std::shared_ptr<IVibratorCallback>&, int32_t*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect>* _aidl_return) {
+    *_aidl_return = {};
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::setExternalControl(bool) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive>*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive, int32_t*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect>&,
+                                     const std::shared_ptr<IVibratorCallback>&) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect>*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t, Effect, EffectStrength) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getResonantFrequency(float*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getQFactor(float*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getFrequencyResolution(float*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float>*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking>*) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle>&,
+                                         const std::shared_ptr<IVibratorCallback>&) {
+    return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+}
+
+}  // namespace aidl::android::hardware::vibrator
diff --git a/tests/extension/vibrator/aidl/default/Vibrator.h b/tests/extension/vibrator/aidl/default/Vibrator.h
new file mode 100644
index 0000000..80916ae
--- /dev/null
+++ b/tests/extension/vibrator/aidl/default/Vibrator.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/vibrator/BnVibrator.h>
+
+namespace aidl::android::hardware::vibrator {
+
+class Vibrator : public BnVibrator {
+    ndk::ScopedAStatus getCapabilities(int32_t* _aidl_return) override;
+    ndk::ScopedAStatus off() override;
+    ndk::ScopedAStatus on(int32_t timeoutMs,
+                          const std::shared_ptr<IVibratorCallback>& callback) override;
+    ndk::ScopedAStatus perform(Effect effect, EffectStrength strength,
+                               const std::shared_ptr<IVibratorCallback>& callback,
+                               int32_t* _aidl_return) override;
+    ndk::ScopedAStatus getSupportedEffects(std::vector<Effect>* _aidl_return) override;
+    ndk::ScopedAStatus setAmplitude(float amplitude) override;
+    ndk::ScopedAStatus setExternalControl(bool enabled) override;
+    ndk::ScopedAStatus getCompositionDelayMax(int32_t* maxDelayMs);
+    ndk::ScopedAStatus getCompositionSizeMax(int32_t* maxSize);
+    ndk::ScopedAStatus getSupportedPrimitives(std::vector<CompositePrimitive>* supported) override;
+    ndk::ScopedAStatus getPrimitiveDuration(CompositePrimitive primitive,
+                                            int32_t* durationMs) override;
+    ndk::ScopedAStatus compose(const std::vector<CompositeEffect>& composite,
+                               const std::shared_ptr<IVibratorCallback>& callback) override;
+    ndk::ScopedAStatus getSupportedAlwaysOnEffects(std::vector<Effect>* _aidl_return) override;
+    ndk::ScopedAStatus alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) override;
+    ndk::ScopedAStatus alwaysOnDisable(int32_t id) override;
+    ndk::ScopedAStatus getResonantFrequency(float* resonantFreqHz) override;
+    ndk::ScopedAStatus getQFactor(float* qFactor) override;
+    ndk::ScopedAStatus getFrequencyResolution(float* freqResolutionHz) override;
+    ndk::ScopedAStatus getFrequencyMinimum(float* freqMinimumHz) override;
+    ndk::ScopedAStatus getBandwidthAmplitudeMap(std::vector<float>* _aidl_return) override;
+    ndk::ScopedAStatus getPwlePrimitiveDurationMax(int32_t* durationMs) override;
+    ndk::ScopedAStatus getPwleCompositionSizeMax(int32_t* maxSize) override;
+    ndk::ScopedAStatus getSupportedBraking(std::vector<Braking>* supported) override;
+    ndk::ScopedAStatus composePwle(const std::vector<PrimitivePwle>& composite,
+                                   const std::shared_ptr<IVibratorCallback>& callback) override;
+};
+
+}  // namespace aidl::android::hardware::vibrator
diff --git a/tests/extension/vibrator/aidl/default/service.cpp b/tests/extension/vibrator/aidl/default/service.cpp
index 16290df..5917d0f 100644
--- a/tests/extension/vibrator/aidl/default/service.cpp
+++ b/tests/extension/vibrator/aidl/default/service.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include <vibrator-impl/Vibrator.h>
 #include "CustomVibrator.h"
+#include "Vibrator.h"
 
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
diff --git a/tests/libhwbinder/aidl/android/tests/binder/IBenchmark.aidl b/tests/libhwbinder/aidl/android/tests/binder/IBenchmark.aidl
index be91fb9..bc44e95 100644
--- a/tests/libhwbinder/aidl/android/tests/binder/IBenchmark.aidl
+++ b/tests/libhwbinder/aidl/android/tests/binder/IBenchmark.aidl
@@ -1,5 +1,6 @@
 package android.tests.binder;
 
 interface IBenchmark {
-  byte[] sendVec(in byte[] data);
-}
\ No newline at end of file
+    byte[] sendVec(in byte[] data);
+    IBinder[] sendBinderVec(in IBinder[] data);
+}
diff --git a/tests/msgq/1.0/ITestMsgQ.hal b/tests/msgq/1.0/ITestMsgQ.hal
index 0cf9c7c..62bef0a 100644
--- a/tests/msgq/1.0/ITestMsgQ.hal
+++ b/tests/msgq/1.0/ITestMsgQ.hal
@@ -18,8 +18,8 @@
 
 interface ITestMsgQ {
     enum EventFlagBits : uint32_t {
-        FMQ_NOT_EMPTY = 1 << 0,
-        FMQ_NOT_FULL  = 1 << 1,
+        FMQ_NOT_FULL = 1 << 0,
+        FMQ_NOT_EMPTY  = 1 << 1,
     };
 
     /**
diff --git a/tests/msgq/TEST_MAPPING b/tests/msgq/TEST_MAPPING
new file mode 100644
index 0000000..51c6c97
--- /dev/null
+++ b/tests/msgq/TEST_MAPPING
@@ -0,0 +1,18 @@
+{
+  "presubmit": [
+    {
+      "name": "fmq_unit_tests"
+    },
+    {
+      "name": "fmq_test"
+    }
+  ],
+  "hwasan-presubmit": [
+    {
+      "name": "fmq_unit_tests"
+    },
+    {
+      "name": "fmq_test"
+    }
+  ]
+}
diff --git a/tetheroffload/aidl/vts/functional/Android.bp b/tetheroffload/aidl/vts/functional/Android.bp
index 74edab0..a379cf7 100644
--- a/tetheroffload/aidl/vts/functional/Android.bp
+++ b/tetheroffload/aidl/vts/functional/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_pixel_connectivity_networking",
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
diff --git a/tetheroffload/config/1.0/vts/functional/Android.bp b/tetheroffload/config/1.0/vts/functional/Android.bp
index fe03d8f..cbc0bb2 100644
--- a/tetheroffload/config/1.0/vts/functional/Android.bp
+++ b/tetheroffload/config/1.0/vts/functional/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_pixel_connectivity_networking",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/tetheroffload/control/1.0/vts/functional/Android.bp b/tetheroffload/control/1.0/vts/functional/Android.bp
index dc3b00c..8aa625e 100644
--- a/tetheroffload/control/1.0/vts/functional/Android.bp
+++ b/tetheroffload/control/1.0/vts/functional/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_pixel_connectivity_networking",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/tetheroffload/control/1.1/vts/functional/Android.bp b/tetheroffload/control/1.1/vts/functional/Android.bp
index 3eea59b..01731dd 100644
--- a/tetheroffload/control/1.1/vts/functional/Android.bp
+++ b/tetheroffload/control/1.1/vts/functional/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_pixel_connectivity_networking",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/thermal/1.0/vts/functional/Android.bp b/thermal/1.0/vts/functional/Android.bp
index c73008a..d3db67c 100644
--- a/thermal/1.0/vts/functional/Android.bp
+++ b/thermal/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_games",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/thermal/1.1/vts/functional/Android.bp b/thermal/1.1/vts/functional/Android.bp
index 89fef1b..6e4e003 100644
--- a/thermal/1.1/vts/functional/Android.bp
+++ b/thermal/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_games",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/thermal/2.0/vts/functional/Android.bp b/thermal/2.0/vts/functional/Android.bp
index 29dffcb..e959bc8 100644
--- a/thermal/2.0/vts/functional/Android.bp
+++ b/thermal/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_games",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/thermal/OWNERS b/thermal/OWNERS
index 7229b22..13895bd 100644
--- a/thermal/OWNERS
+++ b/thermal/OWNERS
@@ -1,5 +1,3 @@
 # Bug component: 826709
-
-# ADPF virtual team
-lpy@google.com
+file:platform/frameworks/base:/ADPF_OWNERS
 wvw@google.com
diff --git a/thermal/aidl/vts/Android.bp b/thermal/aidl/vts/Android.bp
index 0812811..35f7649 100644
--- a/thermal/aidl/vts/Android.bp
+++ b/thermal/aidl/vts/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_games",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/threadnetwork/aidl/default/Android.bp b/threadnetwork/aidl/default/Android.bp
index 82a76e0..a840fa3 100644
--- a/threadnetwork/aidl/default/Android.bp
+++ b/threadnetwork/aidl/default/Android.bp
@@ -14,6 +14,8 @@
     vendor: true,
     relative_install_path: "hw",
 
+    defaults: ["android.hardware.threadnetwork-service.defaults"],
+
     shared_libs: [
         "libbinder_ndk",
         "liblog",
@@ -43,6 +45,17 @@
     ],
 }
 
+cc_defaults {
+    name: "android.hardware.threadnetwork-service.defaults",
+    product_variables: {
+        debuggable: {
+            cppflags: [
+                "-DDEV_BUILD",
+            ],
+        },
+    },
+}
+
 cc_fuzz {
     name: "android.hardware.threadnetwork-service.fuzzer",
 
@@ -90,10 +103,20 @@
     installable: false,
 }
 
+filegroup {
+    name: "com.android.hardware.threadnetwork_manifest",
+    srcs: ["manifest.json"],
+}
+
+filegroup {
+    name: "com.android.hardware.threadnetwork_file_contexts",
+    srcs: ["file_contexts"],
+}
+
 apex {
     name: "com.android.hardware.threadnetwork",
-    manifest: "manifest.json",
-    file_contexts: "file_contexts",
+    manifest: ":com.android.hardware.threadnetwork_manifest",
+    file_contexts: ":com.android.hardware.threadnetwork_file_contexts",
     key: "com.android.hardware.key",
     certificate: ":com.android.hardware.certificate",
     updatable: false,
@@ -110,3 +133,21 @@
         "android.hardware.thread_network.prebuilt.xml", // permission
     ],
 }
+
+prebuilt_etc {
+    name: "threadnetwork-service-simulation-rcp.rc",
+    src: "threadnetwork-service-simulation-rcp.rc",
+    installable: false,
+}
+
+// Thread HAL service which uses a simulation RCP (i.e. ot-rcp),
+// typically used in emulator devices.
+override_apex {
+    name: "com.android.hardware.threadnetwork-simulation-rcp",
+    base: "com.android.hardware.threadnetwork",
+    prebuilts: [
+        "threadnetwork-service-simulation-rcp.rc",
+        "threadnetwork-default.xml",
+        "android.hardware.thread_network.prebuilt.xml",
+    ],
+}
diff --git a/threadnetwork/aidl/default/socket_interface.cpp b/threadnetwork/aidl/default/socket_interface.cpp
index 339fd6b..71c6b4f 100644
--- a/threadnetwork/aidl/default/socket_interface.cpp
+++ b/threadnetwork/aidl/default/socket_interface.cpp
@@ -36,6 +36,7 @@
 #include <vector>
 
 #include "common/code_utils.hpp"
+#include "openthread/error.h"
 #include "openthread/openthread-system.h"
 #include "platform-posix.h"
 
@@ -56,14 +57,9 @@
 
 otError SocketInterface::Init(ReceiveFrameCallback aCallback, void* aCallbackContext,
                               RxFrameBuffer& aFrameBuffer) {
-    otError error = OT_ERROR_NONE;
+    otError error = InitSocket();
 
-    VerifyOrExit(mSockFd == -1, error = OT_ERROR_ALREADY);
-
-    WaitForSocketFileCreated(mRadioUrl.GetPath());
-
-    mSockFd = OpenFile(mRadioUrl);
-    VerifyOrExit(mSockFd != -1, error = OT_ERROR_FAILED);
+    VerifyOrExit(error == OT_ERROR_NONE);
 
     mReceiveFrameCallback = aCallback;
     mReceiveFrameContext = aCallbackContext;
@@ -94,8 +90,8 @@
 otError SocketInterface::WaitForFrame(uint64_t aTimeoutUs) {
     otError error = OT_ERROR_NONE;
     struct timeval timeout;
-    timeout.tv_sec = static_cast<time_t>(aTimeoutUs / US_PER_S);
-    timeout.tv_usec = static_cast<suseconds_t>(aTimeoutUs % US_PER_S);
+    timeout.tv_sec = static_cast<time_t>(aTimeoutUs / OT_US_PER_S);
+    timeout.tv_usec = static_cast<suseconds_t>(aTimeoutUs % OT_US_PER_S);
 
     fd_set readFds;
     fd_set errorFds;
@@ -133,8 +129,8 @@
 
     while (mIsHardwareResetting && retries++ < kMaxRetriesForSocketCloseCheck) {
         struct timeval timeout;
-        timeout.tv_sec = static_cast<time_t>(aTimeoutMs / MS_PER_S);
-        timeout.tv_usec = static_cast<suseconds_t>((aTimeoutMs % MS_PER_S) * MS_PER_S);
+        timeout.tv_sec = static_cast<time_t>(aTimeoutMs / OT_MS_PER_S);
+        timeout.tv_usec = static_cast<suseconds_t>((aTimeoutMs % OT_MS_PER_S) * OT_MS_PER_S);
 
         fd_set readFds;
 
@@ -155,9 +151,22 @@
 
     VerifyOrExit(!mIsHardwareResetting, error = OT_ERROR_FAILED);
 
-    WaitForSocketFileCreated(mRadioUrl.GetPath());
-    mSockFd = OpenFile(mRadioUrl);
-    VerifyOrExit(mSockFd != -1, error = OT_ERROR_FAILED);
+exit:
+    return error;
+}
+
+otError SocketInterface::InitSocket() {
+    otError error = OT_ERROR_NONE;
+    int retries = 0;
+
+    VerifyOrExit(mSockFd == -1, error = OT_ERROR_ALREADY);
+
+    while (retries++ < kMaxRetriesForSocketInit) {
+        WaitForSocketFileCreated(mRadioUrl.GetPath());
+        mSockFd = OpenFile(mRadioUrl);
+        VerifyOrExit(mSockFd == -1);
+    }
+    error = OT_ERROR_FAILED;
 
 exit:
     return error;
@@ -168,11 +177,16 @@
 
     assert(context != nullptr);
 
+    VerifyOrExit(mSockFd != -1);
+
     FD_SET(mSockFd, &context->mReadFdSet);
 
     if (context->mMaxFd < mSockFd) {
         context->mMaxFd = mSockFd;
     }
+
+exit:
+    return;
 }
 
 void SocketInterface::Process(const void* aMainloopContext) {
@@ -181,9 +195,14 @@
 
     assert(context != nullptr);
 
+    VerifyOrExit(mSockFd != -1);
+
     if (FD_ISSET(mSockFd, &context->mReadFdSet)) {
         Read();
     }
+
+exit:
+    return;
 }
 
 otError SocketInterface::HardwareReset(void) {
@@ -198,22 +217,24 @@
 
 void SocketInterface::Read(void) {
     uint8_t buffer[kMaxFrameSize];
+    ssize_t rval;
 
-    ssize_t rval = TEMP_FAILURE_RETRY(read(mSockFd, buffer, sizeof(buffer)));
+    VerifyOrExit(mSockFd != -1);
+
+    rval = TEMP_FAILURE_RETRY(read(mSockFd, buffer, sizeof(buffer)));
 
     if (rval > 0) {
         ProcessReceivedData(buffer, static_cast<uint16_t>(rval));
     } else if (rval < 0) {
         DieNow(OT_EXIT_ERROR_ERRNO);
     } else {
-        if (mIsHardwareResetting) {
-            LogInfo("Socket connection is closed due to hardware reset.");
-            ResetStates();
-        } else {
-            LogCrit("Socket connection is closed by remote.");
-            exit(OT_EXIT_FAILURE);
-        }
+        LogWarn("Socket connection is closed by remote, isHardwareReset: %d", mIsHardwareResetting);
+        ResetStates();
+        InitSocket();
     }
+
+exit:
+    return;
 }
 
 void SocketInterface::Write(const uint8_t* aFrame, uint16_t aLength) {
@@ -314,8 +335,8 @@
         fd_set fds;
         FD_ZERO(&fds);
         FD_SET(inotifyFd, &fds);
-        struct timeval timeout = {kMaxSelectTimeMs / MS_PER_S,
-                                  (kMaxSelectTimeMs % MS_PER_S) * MS_PER_S};
+        struct timeval timeout = {kMaxSelectTimeMs / OT_MS_PER_S,
+                                  (kMaxSelectTimeMs % OT_MS_PER_S) * OT_MS_PER_S};
 
         int rval = select(inotifyFd + 1, &fds, nullptr, nullptr, &timeout);
         VerifyOrDie(rval >= 0, OT_EXIT_ERROR_ERRNO);
diff --git a/threadnetwork/aidl/default/socket_interface.hpp b/threadnetwork/aidl/default/socket_interface.hpp
index 494d76a..83c86e8 100644
--- a/threadnetwork/aidl/default/socket_interface.hpp
+++ b/threadnetwork/aidl/default/socket_interface.hpp
@@ -247,6 +247,15 @@
     otError WaitForHardwareResetCompletion(uint32_t aTimeoutMs);
 
     /**
+     * Initialize socket
+     *
+     * @retval TRUE  Socket initialization is successful.
+     * @retval FALSE Socket initialization is failed.
+     *
+     */
+    otError InitSocket();
+
+    /**
      * Reset socket interface to intitial state.
      *
      */
@@ -257,6 +266,7 @@
                                              ///< descriptor to become available.
         kMaxRetriesForSocketCloseCheck = 3,  ///< Maximum retry times for checking
                                              ///< if socket is closed.
+        kMaxRetriesForSocketInit = 3,        ///< Maximum retry times for socket initialization.
     };
 
     ReceiveFrameCallback mReceiveFrameCallback;
diff --git a/threadnetwork/aidl/default/threadnetwork-service-simulation-rcp.rc b/threadnetwork/aidl/default/threadnetwork-service-simulation-rcp.rc
new file mode 100644
index 0000000..3b889eb
--- /dev/null
+++ b/threadnetwork/aidl/default/threadnetwork-service-simulation-rcp.rc
@@ -0,0 +1,3 @@
+service vendor.threadnetwork_hal /apex/com.android.hardware.threadnetwork/bin/hw/android.hardware.threadnetwork-service spinel+hdlc+forkpty:///apex/com.android.hardware.threadnetwork/bin/ot-rcp?forkpty-arg=1
+    class hal
+    user thread_network
diff --git a/threadnetwork/aidl/default/utils.cpp b/threadnetwork/aidl/default/utils.cpp
index 3552b3a..740f331 100644
--- a/threadnetwork/aidl/default/utils.cpp
+++ b/threadnetwork/aidl/default/utils.cpp
@@ -43,6 +43,7 @@
 }
 
 void otDumpDebgPlat(const char* aText, const void* aData, uint16_t aDataLength) {
+#ifdef DEV_BUILD
     constexpr uint16_t kBufSize = 512;
     char buf[kBufSize];
 
@@ -55,6 +56,11 @@
 
         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "%s: %s", aText, buf);
     }
+#else
+    OT_UNUSED_VARIABLE(aText);
+    OT_UNUSED_VARIABLE(aData);
+    OT_UNUSED_VARIABLE(aDataLength);
+#endif
 }
 
 OT_TOOL_WEAK void otPlatAlarmMilliFired(otInstance* aInstance) {
diff --git a/threadnetwork/aidl/vts/Android.bp b/threadnetwork/aidl/vts/Android.bp
index 931081b..f489039 100644
--- a/threadnetwork/aidl/vts/Android.bp
+++ b/threadnetwork/aidl/vts/Android.bp
@@ -16,6 +16,7 @@
 
 cc_test {
     name: "VtsHalThreadNetworkTargetTest",
+    team: "trendy_team_fwk_thread_network",
     defaults: [
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
diff --git a/tv/input/1.0/vts/functional/Android.bp b/tv/input/1.0/vts/functional/Android.bp
index fad1c90..57d81e2 100644
--- a/tv/input/1.0/vts/functional/Android.bp
+++ b/tv/input/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_interactive_tv",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
index 6187c73..9f3466a 100644
--- a/tv/tuner/1.0/vts/functional/Android.bp
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_interactive_tv",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/tv/tuner/1.1/vts/functional/Android.bp b/tv/tuner/1.1/vts/functional/Android.bp
index ac835a4..90b2494 100644
--- a/tv/tuner/1.1/vts/functional/Android.bp
+++ b/tv/tuner/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_interactive_tv",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/tv/tuner/aidl/Android.bp b/tv/tuner/aidl/Android.bp
index 6cbf362..efcc327 100644
--- a/tv/tuner/aidl/Android.bp
+++ b/tv/tuner/aidl/Android.bp
@@ -41,6 +41,5 @@
         },
 
     ],
-    frozen: true,
 
 }
diff --git a/tv/tuner/aidl/default/Android.bp b/tv/tuner/aidl/default/Android.bp
index ed97d9c..a76a653 100644
--- a/tv/tuner/aidl/default/Android.bp
+++ b/tv/tuner/aidl/default/Android.bp
@@ -10,7 +10,6 @@
 cc_defaults {
     name: "tuner_hal_example_defaults",
     relative_install_path: "hw",
-    vintf_fragments: ["tuner-default.xml"],
     vendor: true,
     compile_multilib: "first",
     srcs: [
@@ -30,7 +29,7 @@
     ],
     shared_libs: [
         "android.hardware.common.fmq-V1-ndk",
-        "android.hardware.tv.tuner-V2-ndk",
+        "android.hardware.tv.tuner-V3-ndk",
         "libbase",
         "libbinder_ndk",
         "libcutils",
@@ -43,6 +42,15 @@
     header_libs: [
         "media_plugin_headers",
     ],
+    vintf_fragment_modules: [
+        "tuner-default.xml",
+    ],
+}
+
+vintf_fragment {
+    name: "tuner-default.xml",
+    src: "tuner-default.xml",
+    vendor: true,
 }
 
 cc_binary {
diff --git a/tv/tuner/aidl/vts/functional/Android.bp b/tv/tuner/aidl/vts/functional/Android.bp
index 09e63fc..4c961ad 100644
--- a/tv/tuner/aidl/vts/functional/Android.bp
+++ b/tv/tuner/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_interactive_tv",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
@@ -55,7 +56,7 @@
         "android.hardware.cas-V1-ndk",
         "android.hardware.common-V2-ndk",
         "android.hardware.common.fmq-V1-ndk",
-        "android.hardware.tv.tuner-V2-ndk",
+        "android.hardware.tv.tuner-V3-ndk",
         "libaidlcommonsupport",
         "libfmq",
         "libcutils",
diff --git a/usb/1.0/vts/functional/Android.bp b/usb/1.0/vts/functional/Android.bp
index d976a06..09bbeec 100644
--- a/usb/1.0/vts/functional/Android.bp
+++ b/usb/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_usb",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/usb/1.1/vts/functional/Android.bp b/usb/1.1/vts/functional/Android.bp
index f514009..48e36f0 100644
--- a/usb/1.1/vts/functional/Android.bp
+++ b/usb/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_usb",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/usb/1.2/vts/functional/Android.bp b/usb/1.2/vts/functional/Android.bp
index 688e725..62442be 100644
--- a/usb/1.2/vts/functional/Android.bp
+++ b/usb/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_usb",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/usb/1.3/vts/functional/Android.bp b/usb/1.3/vts/functional/Android.bp
index 6a1ce1e..a345128 100644
--- a/usb/1.3/vts/functional/Android.bp
+++ b/usb/1.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_usb",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/usb/OWNERS b/usb/OWNERS
index 3611b4d..647d626 100644
--- a/usb/OWNERS
+++ b/usb/OWNERS
@@ -1,8 +1,8 @@
 # Bug component: 175220
 
-aprasath@google.com
-kumarashishg@google.com
-sarup@google.com
 anothermark@google.com
+febinthattil@google.com
+aprasath@google.com
 albertccwang@google.com
 badhri@google.com
+kumarashishg@google.com
\ No newline at end of file
diff --git a/usb/aidl/vts/Android.bp b/usb/aidl/vts/Android.bp
index cf9299e..d41116a 100644
--- a/usb/aidl/vts/Android.bp
+++ b/usb/aidl/vts/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_usb",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/uwb/aidl/Android.bp b/uwb/aidl/Android.bp
index abd6a23..655d8a2 100755
--- a/uwb/aidl/Android.bp
+++ b/uwb/aidl/Android.bp
@@ -16,6 +16,7 @@
     srcs: ["android/hardware/uwb/*.aidl"],
     stability: "vintf",
     host_supported: true,
+    frozen: true,
     backend: {
         java: {
             sdk_version: "module_Tiramisu",
@@ -56,6 +57,7 @@
     vendor_available: true,
     srcs: ["android/hardware/uwb/fira_android/*.aidl"],
     stability: "vintf",
+    frozen: false,
     backend: {
         java: {
             sdk_version: "module_Tiramisu",
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
index 58919d1..d0f1ed9 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
@@ -35,6 +35,8 @@
 @Backing(type="int") @VintfStability
 enum UwbVendorCapabilityTlvTypes {
   SUPPORTED_POWER_STATS_QUERY = 0xC0,
+  SUPPORTED_ANTENNA_MODES = 0xC1,
+  SUPPORTED_MAX_SESSION_COUNT = 0xEB,
   CCC_SUPPORTED_CHAPS_PER_SLOT = 0xA0,
   CCC_SUPPORTED_SYNC_CODES = 0xA1,
   CCC_SUPPORTED_HOPPING_CONFIG_MODES_AND_SEQUENCES = 0xA2,
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl
index 702e561..d9b7220 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl
@@ -34,6 +34,8 @@
 package android.hardware.uwb.fira_android;
 @Backing(type="long") @VintfStability
 enum UwbVendorCapabilityTlvValues {
+  ANTENNA_MODE_OMNI = 1,
+  ANTENNA_MODE_DIRECTIONAL = (1 << 1) /* 2 */,
   UWB_CONFIG_0 = 0,
   UWB_CONFIG_1 = 1,
   PULSE_SHAPE_SYMMETRICAL_ROOT_RAISED_COSINE = 0,
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
index 4df45b6..2d81ed2 100644
--- a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
@@ -41,6 +41,18 @@
      */
     SUPPORTED_POWER_STATS_QUERY = 0xC0,
 
+    /**
+     * 1 byte bitmask to indicate which antennas modes are supported.
+     * 0x01 = "Omni mode",
+     * 0x02 = "Directional mode",
+     */
+    SUPPORTED_ANTENNA_MODES = 0xC1,
+
+    /**
+     * Int value to indicate max supported session count
+     */
+    SUPPORTED_MAX_SESSION_COUNT = 0xEB,
+
     /*********************************************
      * CCC specific
      ********************************************/
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl
index 6ef52fe..e5165dc 100644
--- a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvValues.aidl
@@ -25,6 +25,12 @@
 @Backing(type="long")
 enum UwbVendorCapabilityTlvValues {
     /*********************************************
+     * Protocol agnostic
+     ********************************************/
+    ANTENNA_MODE_OMNI = 1,
+    ANTENNA_MODE_DIRECTIONAL = 1 << 1,
+
+    /*********************************************
      * CCC specific
      ********************************************/
     UWB_CONFIG_0 = 0,
diff --git a/uwb/aidl/default/Android.bp b/uwb/aidl/default/Android.bp
index eba18cf..037eac3 100644
--- a/uwb/aidl/default/Android.bp
+++ b/uwb/aidl/default/Android.bp
@@ -16,17 +16,13 @@
     prefer_rlib: true,
     rustlibs: [
         "android.hardware.uwb-V1-rust",
-        "liblibc",
         "liblogger",
         "liblog_rust",
         "libbinder_rs",
         "libbinder_tokio_rs",
         "libtokio",
-        "libtokio_util",
         "libnix",
         "libanyhow",
-        "libpdl_runtime",
-        "libuwb_uci_packets",
     ],
     proc_macros: [
         "libasync_trait",
diff --git a/uwb/aidl/default/src/service.rs b/uwb/aidl/default/src/service.rs
index e97b291..80fa8af 100644
--- a/uwb/aidl/default/src/service.rs
+++ b/uwb/aidl/default/src/service.rs
@@ -1,8 +1,6 @@
 use android_hardware_uwb::aidl::android::hardware::uwb::IUwb::{self, IUwb as _};
 use android_hardware_uwb::binder;
 
-use tokio::runtime::Runtime;
-
 use std::env;
 use std::panic;
 
@@ -25,13 +23,12 @@
 
     log::info!("UWB HAL starting up");
 
-    // Create the tokio runtime
-    let rt = Runtime::new()?;
+    let rt = tokio::runtime::Runtime::new()?;
 
     let chips = env::args()
         .skip(1) // Skip binary name
         .enumerate()
-        .map(|(i, arg)| uwb_chip::UwbChip::new(i.to_string(), arg));
+        .map(|(i, arg)| rt.block_on(uwb_chip::UwbChip::new(i.to_string(), arg)));
 
     binder::add_service(
         &format!("{}/default", IUwb::BpUwb::get_descriptor()),
diff --git a/uwb/aidl/default/src/uwb_chip.rs b/uwb/aidl/default/src/uwb_chip.rs
index 956cf6c..0ed05d8 100644
--- a/uwb/aidl/default/src/uwb_chip.rs
+++ b/uwb/aidl/default/src/uwb_chip.rs
@@ -7,126 +7,113 @@
 use binder::{DeathRecipient, IBinder, Result, Strong};
 
 use std::sync::Arc;
-use tokio::io::unix::AsyncFd;
-use tokio::select;
+use tokio::fs;
+use tokio::io::{AsyncReadExt, AsyncWriteExt};
 use tokio::sync::Mutex;
-use tokio_util::sync::CancellationToken;
 
-use std::fs::{File, OpenOptions};
-use std::io::{self, Read, Write};
-use std::os::unix::fs::OpenOptionsExt;
-
-use pdl_runtime::Packet;
-use uwb_uci_packets::{DeviceResetCmdBuilder, ResetConfig, UciControlPacket, UciControlPacketHal};
-
-enum State {
+enum ClientState {
     Closed,
     Opened {
         callbacks: Strong<dyn IUwbClientCallback>,
-        handle: tokio::task::JoinHandle<()>,
-        serial: File,
-        death_recipient: DeathRecipient,
-        token: CancellationToken,
+        _death_recipient: DeathRecipient,
     },
 }
 
+struct ServiceState {
+    client_state: ClientState,
+    writer: fs::File,
+}
+
 pub struct UwbChip {
     name: String,
-    path: String,
-    state: Arc<Mutex<State>>,
+    _handle: tokio::task::JoinHandle<()>,
+    service_state: Arc<Mutex<ServiceState>>,
 }
 
-impl UwbChip {
-    pub fn new(name: String, path: String) -> Self {
-        Self {
-            name,
-            path,
-            state: Arc::new(Mutex::new(State::Closed)),
-        }
-    }
-}
-
-impl State {
-    /// Terminate the reader task.
-    async fn close(&mut self) -> Result<()> {
-        if let State::Opened {
-            ref mut token,
-            ref callbacks,
-            ref mut death_recipient,
-            ref mut handle,
-            ref mut serial,
-        } = *self
-        {
-            log::info!("waiting for task cancellation");
-            callbacks.as_binder().unlink_to_death(death_recipient)?;
-            token.cancel();
-            handle.await.unwrap();
-            let packet: UciControlPacket = DeviceResetCmdBuilder {
-                reset_config: ResetConfig::UwbsReset,
-            }
-            .build()
-            .into();
-            // DeviceResetCmd need to be send to reset the device to stop all running
-            // activities on UWBS.
-            let packet_vec: Vec<UciControlPacketHal> = packet.into();
-            for hal_packet in packet_vec.into_iter() {
-                serial
-                    .write(&hal_packet.encode_to_vec().unwrap())
-                    .map(|written| written as i32)
-                    .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
-            }
-            consume_device_reset_rsp_and_ntf(
-                &mut serial
-                    .try_clone()
-                    .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?,
-            );
-            log::info!("task successfully cancelled");
-            callbacks.onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK)?;
-            *self = State::Closed;
-        }
-        Ok(())
-    }
-}
-
-fn consume_device_reset_rsp_and_ntf(reader: &mut File) {
-    // Poll the DeviceResetRsp and DeviceStatusNtf before hal is closed to prevent
-    // the host from getting response and notifications from a 'powered down' UWBS.
-    // Do nothing when these packets are received.
-    const DEVICE_RESET_RSP: [u8; 5] = [64, 0, 0, 1, 0];
-    const DEVICE_STATUS_NTF: [u8; 5] = [96, 1, 0, 1, 1];
-    let mut buffer = vec![0; DEVICE_RESET_RSP.len() + DEVICE_STATUS_NTF.len()];
-    read_exact(reader, &mut buffer).unwrap();
-
-    // Make sure received packets are the expected ones.
-    assert_eq!(&buffer[0..DEVICE_RESET_RSP.len()], &DEVICE_RESET_RSP);
-    assert_eq!(&buffer[DEVICE_RESET_RSP.len()..], &DEVICE_STATUS_NTF);
-}
-
-pub fn makeraw(file: File) -> io::Result<File> {
-    // Configure the file descriptor as raw fd.
+/// Configure a file descriptor as raw fd.
+pub fn makeraw(file: fs::File) -> std::io::Result<fs::File> {
     use nix::sys::termios::*;
     let mut attrs = tcgetattr(&file)?;
     cfmakeraw(&mut attrs);
     tcsetattr(&file, SetArg::TCSANOW, &attrs)?;
-
     Ok(file)
 }
 
-/// Wrapper around Read::read to handle EWOULDBLOCK.
-/// /!\ will actively wait for more data, make sure to call
-/// this method only when data is immediately expected.
-fn read_exact(file: &mut File, mut buf: &mut [u8]) -> io::Result<()> {
-    while buf.len() > 0 {
-        match file.read(buf) {
-            Ok(0) => panic!("unexpectedly reached end of file"),
-            Ok(read_len) => buf = &mut buf[read_len..],
-            Err(err) if err.kind() == io::ErrorKind::WouldBlock => continue,
-            Err(err) => return Err(err),
+impl UwbChip {
+    pub async fn new(name: String, path: String) -> Self {
+        // Open the serial file and configure it as raw file
+        // descriptor.
+        let mut reader = fs::OpenOptions::new()
+            .read(true)
+            .write(true)
+            .create(false)
+            .open(&path)
+            .await
+            .and_then(makeraw)
+            .expect("failed to open the serial device");
+        let writer = reader
+            .try_clone()
+            .await
+            .expect("failed to clone serial for writing");
+
+        // Create the chip
+        let service_state = Arc::new(Mutex::new(ServiceState {
+            writer,
+            client_state: ClientState::Closed,
+        }));
+
+        // Spawn the task that will run the polling loop.
+        let handle = {
+            let service_state = service_state.clone();
+
+            tokio::task::spawn(async move {
+                log::info!("UCI reader task started");
+
+                const MESSAGE_TYPE_MASK: u8 = 0b11100000;
+                const DATA_MESSAGE_TYPE: u8 = 0b000;
+                const UCI_HEADER_SIZE: usize = 4;
+                const UCI_BUFFER_SIZE: usize = 1024;
+
+                let mut buffer = [0; UCI_BUFFER_SIZE];
+
+                loop {
+                    reader
+                        .read_exact(&mut buffer[0..UCI_HEADER_SIZE])
+                        .await
+                        .expect("failed to read uci header bytes");
+                    let common_header = buffer[0];
+                    let mt = (common_header & MESSAGE_TYPE_MASK) >> 5;
+                    let payload_length = if mt == DATA_MESSAGE_TYPE {
+                        u16::from_le_bytes([buffer[2], buffer[3]]) as usize
+                    } else {
+                        buffer[3] as usize
+                    };
+
+                    let total_packet_length = payload_length + UCI_HEADER_SIZE;
+                    reader
+                        .read_exact(&mut buffer[UCI_HEADER_SIZE..total_packet_length])
+                        .await
+                        .expect("failed to read uci payload bytes");
+
+                    log::debug!(" <-- {:?}", &buffer[0..total_packet_length]);
+
+                    let service_state = service_state.lock().await;
+                    if let ClientState::Opened { ref callbacks, .. } = service_state.client_state {
+                        callbacks
+                            .onUciMessage(&buffer[0..total_packet_length])
+                            .unwrap();
+                    }
+                }
+            })
+        };
+
+        Self {
+            name,
+            _handle: handle,
+            service_state,
         }
     }
-    Ok(())
 }
-
 impl binder::Interface for UwbChip {}
 
 #[async_trait]
@@ -136,124 +123,30 @@
     }
 
     async fn open(&self, callbacks: &Strong<dyn IUwbClientCallback>) -> Result<()> {
-        log::debug!("open: {:?}", &self.path);
+        log::debug!("open");
 
-        let mut state = self.state.lock().await;
+        let mut service_state = self.service_state.lock().await;
 
-        if matches!(*state, State::Opened { .. }) {
+        if matches!(service_state.client_state, ClientState::Opened { .. }) {
             log::error!("the state is already opened");
             return Err(binder::ExceptionCode::ILLEGAL_STATE.into());
         }
 
-        let serial = OpenOptions::new()
-            .read(true)
-            .write(true)
-            .create(false)
-            .custom_flags(libc::O_NONBLOCK)
-            .open(&self.path)
-            .and_then(makeraw)
-            .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
-
-        let state_death_recipient = self.state.clone();
-        let mut death_recipient = DeathRecipient::new(move || {
-            let mut state = state_death_recipient.blocking_lock();
-            log::info!("Uwb service has died");
-            if let State::Opened { ref mut token, .. } = *state {
-                token.cancel();
-                *state = State::Closed;
-            }
-        });
+        let mut death_recipient = {
+            let service_state = self.service_state.clone();
+            DeathRecipient::new(move || {
+                log::info!("Uwb service has died");
+                let mut service_state = service_state.blocking_lock();
+                service_state.client_state = ClientState::Closed;
+            })
+        };
 
         callbacks.as_binder().link_to_death(&mut death_recipient)?;
-
-        let token = CancellationToken::new();
-        let cloned_token = token.clone();
-
-        let client_callbacks = callbacks.clone();
-
-        let reader = serial
-            .try_clone()
-            .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
-
-        let join_handle = tokio::task::spawn(async move {
-            log::info!("UCI reader task started");
-            let mut reader = AsyncFd::new(reader).unwrap();
-
-            loop {
-                const MESSAGE_TYPE_MASK: u8 = 0b11100000;
-                const DATA_MESSAGE_TYPE: u8 = 0b000;
-                const UWB_HEADER_SIZE: usize = 4;
-                let mut buffer = vec![0; UWB_HEADER_SIZE];
-
-                // The only time where the task can be safely
-                // cancelled is when no packet bytes have been read.
-                //
-                // - read_exact() cannot be used here since it is not
-                //   cancellation safe.
-                // - read() cannot be used because it cannot be cancelled:
-                //   the syscall is executed blocking on the threadpool
-                //   and completes after termination of the task when
-                //   the pipe receives more data.
-                let read_len = loop {
-                    // On some platforms, the readiness detecting mechanism
-                    // relies on edge-triggered notifications. This means that
-                    // the OS will only notify Tokio when the file descriptor
-                    // transitions from not-ready to ready. For this to work
-                    // you should first try to read or write and only poll for
-                    // readiness if that fails with an error of
-                    // std::io::ErrorKind::WouldBlock.
-                    match reader.get_mut().read(&mut buffer) {
-                        Ok(0) => {
-                            log::error!("file unexpectedly closed");
-                            return;
-                        }
-                        Ok(read_len) => break read_len,
-                        Err(err) if err.kind() == io::ErrorKind::WouldBlock => (),
-                        Err(_) => panic!("unexpected read failure"),
-                    }
-
-                    let mut guard = select! {
-                        _ = cloned_token.cancelled() => {
-                            log::info!("task is cancelled!");
-                            return;
-                        },
-                        result = reader.readable() => result.unwrap()
-                    };
-
-                    guard.clear_ready();
-                };
-
-                // Read the remaining header bytes, if truncated.
-                read_exact(reader.get_mut(), &mut buffer[read_len..]).unwrap();
-
-                let common_header = buffer[0];
-                let mt = (common_header & MESSAGE_TYPE_MASK) >> 5;
-                let payload_length = if mt == DATA_MESSAGE_TYPE {
-                    let payload_length_fields: [u8; 2] = buffer[2..=3].try_into().unwrap();
-                    u16::from_le_bytes(payload_length_fields) as usize
-                } else {
-                    buffer[3] as usize
-                };
-
-                let length = payload_length + UWB_HEADER_SIZE;
-                buffer.resize(length, 0);
-
-                // Read the payload bytes.
-                read_exact(reader.get_mut(), &mut buffer[UWB_HEADER_SIZE..]).unwrap();
-
-                log::debug!(" <-- {:?}", buffer);
-                client_callbacks.onUciMessage(&buffer).unwrap();
-            }
-        });
-
         callbacks.onHalEvent(UwbEvent::OPEN_CPLT, UwbStatus::OK)?;
 
-        *state = State::Opened {
+        service_state.client_state = ClientState::Opened {
             callbacks: callbacks.clone(),
-            handle: join_handle,
-            serial,
-            death_recipient,
-            token,
+            _death_recipient: death_recipient,
         };
 
         Ok(())
@@ -262,19 +155,42 @@
     async fn close(&self) -> Result<()> {
         log::debug!("close");
 
-        let mut state = self.state.lock().await;
+        let mut service_state = self.service_state.lock().await;
 
-        if let State::Opened { .. } = *state {
-            state.close().await
-        } else {
-            Err(binder::ExceptionCode::ILLEGAL_STATE.into())
+        if matches!(service_state.client_state, ClientState::Closed) {
+            log::error!("the state is already closed");
+            return Err(binder::ExceptionCode::ILLEGAL_STATE.into());
         }
+
+        // Send the command Device Reset to stop all running activities
+        // on the UWBS emulator. This is necessary because the emulator
+        // is otherwise not notified of the power down (the serial stays
+        // open).
+        //
+        // The response to the command will be dropped by the polling loop,
+        // as the callbacks will have been removed then.
+        let uci_core_device_reset_cmd = [0x20, 0x00, 0x00, 0x01, 0x00];
+
+        service_state
+            .writer
+            .write_all(&uci_core_device_reset_cmd)
+            .await
+            .expect("failed to write UCI Device Reset command");
+
+        if let ClientState::Opened { ref callbacks, .. } = service_state.client_state {
+            callbacks.onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK)?;
+        }
+
+        service_state.client_state = ClientState::Closed;
+        Ok(())
     }
 
     async fn coreInit(&self) -> Result<()> {
         log::debug!("coreInit");
 
-        if let State::Opened { ref callbacks, .. } = *self.state.lock().await {
+        let service_state = self.service_state.lock().await;
+
+        if let ClientState::Opened { ref callbacks, .. } = service_state.client_state {
             callbacks.onHalEvent(UwbEvent::POST_INIT_CPLT, UwbStatus::OK)?;
             Ok(())
         } else {
@@ -289,22 +205,27 @@
     }
 
     async fn getSupportedAndroidUciVersion(&self) -> Result<i32> {
+        log::debug!("getSupportedAndroidUciVersion");
+
         Ok(1)
     }
 
     async fn sendUciMessage(&self, data: &[u8]) -> Result<i32> {
         log::debug!("sendUciMessage");
 
-        if let State::Opened { ref mut serial, .. } = &mut *self.state.lock().await {
-            log::debug!(" --> {:?}", data);
-            let result = serial
-                .write_all(data)
-                .map(|_| data.len() as i32)
-                .map_err(|_| binder::StatusCode::UNKNOWN_ERROR.into());
-            log::debug!(" status: {:?}", result);
-            result
-        } else {
-            Err(binder::ExceptionCode::ILLEGAL_STATE.into())
+        let mut service_state = self.service_state.lock().await;
+
+        if matches!(service_state.client_state, ClientState::Closed) {
+            log::error!("the state is not opened");
+            return Err(binder::ExceptionCode::ILLEGAL_STATE.into());
         }
+
+        log::debug!(" --> {:?}", data);
+        service_state
+            .writer
+            .write_all(data)
+            .await
+            .map(|_| data.len() as i32)
+            .map_err(|_| binder::StatusCode::UNKNOWN_ERROR.into())
     }
 }
diff --git a/uwb/aidl/vts/VtsHalUwbTargetTest.cpp b/uwb/aidl/vts/VtsHalUwbTargetTest.cpp
index 548cae0..2b09f7e 100644
--- a/uwb/aidl/vts/VtsHalUwbTargetTest.cpp
+++ b/uwb/aidl/vts/VtsHalUwbTargetTest.cpp
@@ -201,14 +201,15 @@
     EXPECT_EQ(retrieved_chip_name, chip_name);
 }
 
-/**
 TEST_P(UwbAidl, ChipSendUciMessage_GetDeviceInfo) {
-const auto iuwb_chip = getAnyChipAndOpen(callback);
-EXPECT_TRUE(iuwb_chip->coreInit(callback).isOk());
+    const auto iuwb_chip = getAnyChipAndOpen();
+    EXPECT_TRUE(iuwb_chip->coreInit().isOk());
 
-const std::vector<uint8_t>
-EXPECT_TRUE(iuwb_chip->sendUciMessage().isOk());
-} */
+    std::vector<uint8_t> uciMessage = {0x20, 0x02, 0x00, 0x00}; /** CoreGetDeviceInfo */
+    int32_t* return_status = new int32_t;
+    EXPECT_TRUE(iuwb_chip->sendUciMessage(uciMessage, return_status).isOk());
+    EXPECT_EQ(*return_status, 4 /* Status Ok */);
+}
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UwbAidl);
 INSTANTIATE_TEST_SUITE_P(Uwb, UwbAidl,
diff --git a/vibrator/1.0/vts/functional/Android.bp b/vibrator/1.0/vts/functional/Android.bp
index 83377e7..c62dc42 100644
--- a/vibrator/1.0/vts/functional/Android.bp
+++ b/vibrator/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_haptics_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/vibrator/1.1/vts/functional/Android.bp b/vibrator/1.1/vts/functional/Android.bp
index f97a343..c7dadc5 100644
--- a/vibrator/1.1/vts/functional/Android.bp
+++ b/vibrator/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_haptics_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/vibrator/1.2/vts/functional/Android.bp b/vibrator/1.2/vts/functional/Android.bp
index 40171ae..4d5de1f 100644
--- a/vibrator/1.2/vts/functional/Android.bp
+++ b/vibrator/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_haptics_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/vibrator/1.3/vts/functional/Android.bp b/vibrator/1.3/vts/functional/Android.bp
index 0fcbf07..3221fa2 100644
--- a/vibrator/1.3/vts/functional/Android.bp
+++ b/vibrator/1.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_haptics_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/vibrator/aidl/Android.bp b/vibrator/aidl/Android.bp
index b5199e2..b2d98f5 100644
--- a/vibrator/aidl/Android.bp
+++ b/vibrator/aidl/Android.bp
@@ -15,14 +15,33 @@
     srcs: [
         "android/hardware/vibrator/*.aidl",
     ],
+    headers: [
+        "PersistableBundle_aidl",
+    ],
     stability: "vintf",
     backend: {
         java: {
             sdk_version: "system_current",
         },
+        ndk: {
+            enabled: true,
+        },
+        cpp: {
+            enabled: false,
+        },
+        rust: {
+            enabled: false,
+        },
     },
-    versions: [
-        "1",
-        "2",
+    versions_with_info: [
+        {
+            version: "1",
+            imports: [],
+        },
+        {
+            version: "2",
+            imports: [],
+        },
     ],
+    frozen: false,
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
index b7afb66..0dcc657 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
@@ -58,15 +58,23 @@
   int getPwleCompositionSizeMax();
   android.hardware.vibrator.Braking[] getSupportedBraking();
   void composePwle(in android.hardware.vibrator.PrimitivePwle[] composite, in android.hardware.vibrator.IVibratorCallback callback);
-  const int CAP_ON_CALLBACK = 1;
-  const int CAP_PERFORM_CALLBACK = 2;
-  const int CAP_AMPLITUDE_CONTROL = 4;
-  const int CAP_EXTERNAL_CONTROL = 8;
-  const int CAP_EXTERNAL_AMPLITUDE_CONTROL = 16;
-  const int CAP_COMPOSE_EFFECTS = 32;
-  const int CAP_ALWAYS_ON_CONTROL = 64;
-  const int CAP_GET_RESONANT_FREQUENCY = 128;
-  const int CAP_GET_Q_FACTOR = 256;
-  const int CAP_FREQUENCY_CONTROL = 512;
-  const int CAP_COMPOSE_PWLE_EFFECTS = 1024;
+  void performVendorEffect(in android.hardware.vibrator.VendorEffect vendorEffect, in android.hardware.vibrator.IVibratorCallback callback);
+  List<android.hardware.vibrator.PwleV2OutputMapEntry> getPwleV2FrequencyToOutputAccelerationMap();
+  int getPwleV2PrimitiveDurationMaxMillis();
+  int getPwleV2CompositionSizeMax();
+  int getPwleV2PrimitiveDurationMinMillis();
+  void composePwleV2(in android.hardware.vibrator.PwleV2Primitive[] composite, in android.hardware.vibrator.IVibratorCallback callback);
+  const int CAP_ON_CALLBACK = (1 << 0) /* 1 */;
+  const int CAP_PERFORM_CALLBACK = (1 << 1) /* 2 */;
+  const int CAP_AMPLITUDE_CONTROL = (1 << 2) /* 4 */;
+  const int CAP_EXTERNAL_CONTROL = (1 << 3) /* 8 */;
+  const int CAP_EXTERNAL_AMPLITUDE_CONTROL = (1 << 4) /* 16 */;
+  const int CAP_COMPOSE_EFFECTS = (1 << 5) /* 32 */;
+  const int CAP_ALWAYS_ON_CONTROL = (1 << 6) /* 64 */;
+  const int CAP_GET_RESONANT_FREQUENCY = (1 << 7) /* 128 */;
+  const int CAP_GET_Q_FACTOR = (1 << 8) /* 256 */;
+  const int CAP_FREQUENCY_CONTROL = (1 << 9) /* 512 */;
+  const int CAP_COMPOSE_PWLE_EFFECTS = (1 << 10) /* 1024 */;
+  const int CAP_PERFORM_VENDOR_EFFECTS = (1 << 11) /* 2048 */;
+  const int CAP_COMPOSE_PWLE_EFFECTS_V2 = (1 << 12) /* 4096 */;
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
index 290c68d..ef5794c 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
@@ -40,12 +40,12 @@
   void prepareSynced(in int[] vibratorIds);
   void triggerSynced(in android.hardware.vibrator.IVibratorCallback callback);
   void cancelSynced();
-  const int CAP_SYNC = 1;
-  const int CAP_PREPARE_ON = 2;
-  const int CAP_PREPARE_PERFORM = 4;
-  const int CAP_PREPARE_COMPOSE = 8;
-  const int CAP_MIXED_TRIGGER_ON = 16;
-  const int CAP_MIXED_TRIGGER_PERFORM = 32;
-  const int CAP_MIXED_TRIGGER_COMPOSE = 64;
-  const int CAP_TRIGGER_CALLBACK = 128;
+  const int CAP_SYNC = (1 << 0) /* 1 */;
+  const int CAP_PREPARE_ON = (1 << 1) /* 2 */;
+  const int CAP_PREPARE_PERFORM = (1 << 2) /* 4 */;
+  const int CAP_PREPARE_COMPOSE = (1 << 3) /* 8 */;
+  const int CAP_MIXED_TRIGGER_ON = (1 << 4) /* 16 */;
+  const int CAP_MIXED_TRIGGER_PERFORM = (1 << 5) /* 32 */;
+  const int CAP_MIXED_TRIGGER_COMPOSE = (1 << 6) /* 64 */;
+  const int CAP_TRIGGER_CALLBACK = (1 << 7) /* 128 */;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
similarity index 88%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
index ca8b3eb..a5eda52 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -31,8 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.vibrator;
+@VintfStability
+parcelable PwleV2OutputMapEntry {
+  float frequencyHz;
+  float maxOutputAccelerationGs;
 }
diff --git a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2Primitive.aidl
similarity index 88%
copy from staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
copy to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2Primitive.aidl
index ca8b3eb..c4f3ea9 100644
--- a/staging/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see/current/android/hardware/security/see/hwcrypto/types/OperationType.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2Primitive.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -31,8 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.see.hwcrypto.types;
-enum OperationType {
-  READ,
-  WRITE,
+package android.hardware.vibrator;
+@VintfStability
+parcelable PwleV2Primitive {
+  float amplitude;
+  float frequencyHz;
+  int timeMillis;
 }
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/VendorEffect.aidl
similarity index 86%
rename from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
rename to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/VendorEffect.aidl
index c1dc51c..62a7380 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/VendorEffect.aidl
@@ -31,10 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.vibrator;
 @VintfStability
-union AcquiredInfoAndVendorCode {
-  android.hardware.biometrics.fingerprint.AcquiredInfo acquiredInfo = android.hardware.biometrics.fingerprint.AcquiredInfo.UNKNOWN;
-  int vendorCode;
+parcelable VendorEffect {
+  android.os.PersistableBundle vendorData;
+  android.hardware.vibrator.EffectStrength strength = android.hardware.vibrator.EffectStrength.MEDIUM;
+  float scale;
+  float vendorScale;
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/Braking.aidl b/vibrator/aidl/android/hardware/vibrator/Braking.aidl
index 2bc51db..f934ff2 100644
--- a/vibrator/aidl/android/hardware/vibrator/Braking.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/Braking.aidl
@@ -23,12 +23,12 @@
      * No braking mechanism used.
      * This is the default if the hardware does not support any braking mechanism.
      */
-    NONE,
+    NONE = 0,
     /**
      * Closed-loop active braking.
      *
      * This effect should produce a sharp, crisp end to the waveform
      * Support is optional.
      */
-    CLAB,
+    CLAB = 1,
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
index 5314898..5f8ee8d 100644
--- a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
@@ -24,13 +24,13 @@
      *
      * Support is required.
      */
-    NOOP,
+    NOOP = 0,
     /**
      * This effect should produce a sharp, crisp click sensation.
      *
      * Support is required.
      */
-    CLICK,
+    CLICK = 1,
     /**
      * A haptic effect that simulates downwards movement with gravity. Often
      * followed by extra energy of hitting and reverberation to augment
@@ -38,43 +38,43 @@
      *
      * Support is optional.
      */
-    THUD,
+    THUD = 2,
     /**
      * A haptic effect that simulates spinning momentum.
      *
      * Support is optional.
      */
-    SPIN,
+    SPIN = 3,
     /**
      * A haptic effect that simulates quick upward movement against gravity.
      *
      * Support is required.
      */
-    QUICK_RISE,
+    QUICK_RISE = 4,
     /**
      * A haptic effect that simulates slow upward movement against gravity.
      *
      * Support is required.
      */
-    SLOW_RISE,
+    SLOW_RISE = 5,
     /**
      * A haptic effect that simulates quick downwards movement with gravity.
      *
      * Support is required.
      */
-    QUICK_FALL,
+    QUICK_FALL = 6,
     /**
      * This very short effect should produce a light crisp sensation intended
      * to be used repetitively for dynamic feedback.
      *
      * Support is required.
      */
-    LIGHT_TICK,
+    LIGHT_TICK = 7,
     /**
      * This very short low frequency effect should produce a light crisp sensation intended
      * to be used repetitively for dynamic feedback.
      *
      * Support is required.
      */
-    LOW_TICK,
+    LOW_TICK = 8,
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/Effect.aidl b/vibrator/aidl/android/hardware/vibrator/Effect.aidl
index c60bfe9..f5cf9e3 100644
--- a/vibrator/aidl/android/hardware/vibrator/Effect.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/Effect.aidl
@@ -24,57 +24,57 @@
      *
      * This effect should produce a sharp, crisp click sensation.
      */
-    CLICK,
+    CLICK = 0,
     /**
      * A double click effect.
      *
      * This effect should produce two sequential sharp, crisp click sensations with a minimal
      * amount of time between them.
      */
-    DOUBLE_CLICK,
+    DOUBLE_CLICK = 1,
     /**
      * A tick effect.
      *
      * This effect should produce a soft, short sensation, like the tick of a clock.
      */
-    TICK,
+    TICK = 2,
     /**
      * A thud effect.
      *
      * This effect should solid feeling bump, like the depression of a heavy mechanical button.
      */
-    THUD,
+    THUD = 3,
     /**
      * A pop effect.
      *
      * A short, quick burst effect.
      */
-    POP,
+    POP = 4,
     /**
      * A heavy click effect.
      *
      * This should produce a sharp striking sensation, like a click but stronger.
      */
-    HEAVY_CLICK,
+    HEAVY_CLICK = 5,
     /**
      * Ringtone patterns. They may correspond with the device's ringtone audio, or may just be a
      * pattern that can be played as a ringtone with any audio, depending on the device.
      */
-    RINGTONE_1,
-    RINGTONE_2,
-    RINGTONE_3,
-    RINGTONE_4,
-    RINGTONE_5,
-    RINGTONE_6,
-    RINGTONE_7,
-    RINGTONE_8,
-    RINGTONE_9,
-    RINGTONE_10,
-    RINGTONE_11,
-    RINGTONE_12,
-    RINGTONE_13,
-    RINGTONE_14,
-    RINGTONE_15,
+    RINGTONE_1 = 6,
+    RINGTONE_2 = 7,
+    RINGTONE_3 = 8,
+    RINGTONE_4 = 9,
+    RINGTONE_5 = 10,
+    RINGTONE_6 = 11,
+    RINGTONE_7 = 12,
+    RINGTONE_8 = 13,
+    RINGTONE_9 = 14,
+    RINGTONE_10 = 15,
+    RINGTONE_11 = 16,
+    RINGTONE_12 = 17,
+    RINGTONE_13 = 18,
+    RINGTONE_14 = 19,
+    RINGTONE_15 = 20,
     /**
      * A soft tick effect meant to be played as a texture.
      *
@@ -82,5 +82,5 @@
      * are expected to be played multiple times in quick succession, replicating a specific
      * texture to the user as a form of haptic feedback.
      */
-    TEXTURE_TICK,
+    TEXTURE_TICK = 21,
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/EffectStrength.aidl b/vibrator/aidl/android/hardware/vibrator/EffectStrength.aidl
index 66f70e5..c6a78d4 100644
--- a/vibrator/aidl/android/hardware/vibrator/EffectStrength.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/EffectStrength.aidl
@@ -19,7 +19,7 @@
 @VintfStability
 @Backing(type="byte")
 enum EffectStrength {
-    LIGHT,
-    MEDIUM,
-    STRONG,
+    LIGHT = 0,
+    MEDIUM = 1,
+    STRONG = 2,
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index b4e7e44..11f36ba 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -16,13 +16,16 @@
 
 package android.hardware.vibrator;
 
-import android.hardware.vibrator.IVibratorCallback;
 import android.hardware.vibrator.Braking;
-import android.hardware.vibrator.Effect;
-import android.hardware.vibrator.EffectStrength;
 import android.hardware.vibrator.CompositeEffect;
 import android.hardware.vibrator.CompositePrimitive;
+import android.hardware.vibrator.Effect;
+import android.hardware.vibrator.EffectStrength;
+import android.hardware.vibrator.IVibratorCallback;
 import android.hardware.vibrator.PrimitivePwle;
+import android.hardware.vibrator.PwleV2OutputMapEntry;
+import android.hardware.vibrator.PwleV2Primitive;
+import android.hardware.vibrator.VendorEffect;
 
 @VintfStability
 interface IVibrator {
@@ -70,6 +73,14 @@
      * Whether composePwle is supported.
      */
     const int CAP_COMPOSE_PWLE_EFFECTS = 1 << 10;
+    /**
+     * Whether perform w/ vendor effect is supported.
+     */
+    const int CAP_PERFORM_VENDOR_EFFECTS = 1 << 11;
+    /**
+     * Whether composePwleV2 for PwlePrimitives is supported.
+     */
+    const int CAP_COMPOSE_PWLE_EFFECTS_V2 = 1 << 12;
 
     /**
      * Determine capabilities of the vibrator HAL (CAP_* mask)
@@ -359,4 +370,103 @@
      * @param composite Array of PWLEs.
      */
     void composePwle(in PrimitivePwle[] composite, in IVibratorCallback callback);
+
+    /**
+     * Fire off a vendor-defined haptic event.
+     *
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_PERFORM_VENDOR_EFFECTS).
+     *
+     * The duration of the effect is unknown and can be undefined for looping effects.
+     * IVibratorCallback.onComplete() support is required for this API.
+     *
+     * Doing this operation while the vibrator is already on is undefined behavior. Clients should
+     * explicitly call off.
+     *
+     * @param effect The vendor data representing the effect to be performed.
+     * @param callback A callback used to inform Frameworks of state change.
+     * @throws :
+     *         - EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities.
+     *         - EX_ILLEGAL_ARGUMENT for bad framework parameters, e.g. scale or effect strength.
+     *         - EX_SERVICE_SPECIFIC for bad vendor data, vibration is not triggered.
+     */
+    void performVendorEffect(in VendorEffect vendorEffect, in IVibratorCallback callback);
+
+    /**
+     * Retrieves a mapping of vibration frequency (Hz) to the maximum achievable output
+     * acceleration (Gs) the device can reach at that frequency.
+     *
+     * The map, represented as a list of `PwleV2OutputMapEntry` (frequency, output acceleration)
+     * pairs, defines the device's frequency response. The platform uses the minimum and maximum
+     * frequency values to determine the supported input range for `IVibrator.composePwleV2`.
+     * Output acceleration values are used to identify a frequency range suitable to safely play
+     * perceivable vibrations with a simple API. The map is also exposed for developers using an
+     * advanced API.
+     *
+     * The platform does not impose specific requirements on map resolution which can vary
+     * depending on the shape of device output curve. The values will be linearly interpolated
+     * during lookups. The platform will provide a simple API, defined by the first frequency range
+     * where output acceleration consistently exceeds a minimum threshold of 10 db SL.
+     *
+     *
+     * This may not be supported and this support is reflected in getCapabilities
+     * (CAP_COMPOSE_PWLE_EFFECTS_V2). If this is supported, it's expected to be non-empty and
+     * describe a valid non-empty frequency range where the simple API can be defined
+     * (i.e. a range where the output acceleration is always above 10 db SL).
+     *
+     * @return A list of map entries representing the frequency to max acceleration
+     *         mapping.
+     * @throws EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities.
+     */
+    List<PwleV2OutputMapEntry> getPwleV2FrequencyToOutputAccelerationMap();
+
+    /**
+     * Retrieve the maximum duration allowed for any primitive PWLE in units of
+     * milliseconds.
+     *
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2).
+     *
+     * @return The maximum duration allowed for a single PrimitivePwle. Non-zero value if supported.
+     * @throws EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities.
+     */
+    int getPwleV2PrimitiveDurationMaxMillis();
+
+    /**
+     * Retrieve the maximum number of PWLE primitives input supported by IVibrator.composePwleV2.
+     *
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2). Devices supporting PWLE effects must
+     * support effects with at least 16 PwleV2Primitive.
+     *
+     * @return The maximum count allowed. Non-zero value if supported.
+     * @throws EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities.
+     */
+    int getPwleV2CompositionSizeMax();
+
+    /**
+     * Retrieves the minimum duration (in milliseconds) of any segment within a
+     * PWLE effect. Devices supporting PWLE effects must support a minimum ramp
+     * time of 20 milliseconds.
+     *
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2).
+     *
+     * @return The minimum duration allowed for a single PrimitivePwle. Non-zero value if supported.
+     * @throws EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities.
+     */
+    int getPwleV2PrimitiveDurationMinMillis();
+
+    /**
+     * Play composed sequence of chirps with optional callback upon completion.
+     *
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2).
+     *
+     * Doing this operation while the vibrator is already on is undefined behavior. Clients should
+     * explicitly call off. IVibratorCallback.onComplete() support is required for this API.
+     *
+     * @param composite An array of primitives that represents a PWLE (Piecewise-Linear Envelope).
+     */
+    void composePwleV2(in PwleV2Primitive[] composite, in IVibratorCallback callback);
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
new file mode 100644
index 0000000..a8db87c
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.vibrator;
+
+@VintfStability
+parcelable PwleV2OutputMapEntry {
+    /**
+     * Absolute frequency point in the units of hertz
+     *
+     */
+    float frequencyHz;
+
+    /**
+     * Max output acceleration for the specified frequency in units of Gs.
+     *
+     * This value represents the maximum safe output acceleration (in Gs) achievable at the
+     * specified frequency, typically determined during calibration. The actual output acceleration
+     * is assumed to scale linearly with the input amplitude within the range of [0, 1].
+     */
+    float maxOutputAccelerationGs;
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl b/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl
new file mode 100644
index 0000000..bd7bec6
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.vibrator;
+
+@VintfStability
+parcelable PwleV2Primitive {
+    /**
+     * Input amplitude ranges from 0.0 (inclusive) to 1.0 (inclusive), representing the relative
+     * input value. Actual output acceleration depends on frequency and device response curve
+     * (see IVibrator.getPwleV2FrequencyToOutputAccelerationMap for max values).
+     *
+     * Input amplitude linearly maps to output acceleration (e.g., 0.5 amplitude yields half the
+     * max acceleration for that frequency).
+     *
+     * 0.0 represents no output acceleration amplitude
+     * 1.0 represents the maximum achievable strength for each frequency, as determined by the
+     *     actuator response curve
+     */
+    float amplitude;
+
+    /**
+     * Absolute frequency point in the units of hertz
+     *
+     * Values are within the continuous inclusive frequency range defined by
+     * IVibrator#getPwleV2FrequencyToOutputAccelerationMap.
+     */
+    float frequencyHz;
+
+    /* Total time from the previous PWLE point to the current one in units of milliseconds. */
+    int timeMillis;
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/VendorEffect.aidl b/vibrator/aidl/android/hardware/vibrator/VendorEffect.aidl
new file mode 100644
index 0000000..6b1af53
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/VendorEffect.aidl
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.vibrator;
+
+import android.hardware.vibrator.EffectStrength;
+import android.os.PersistableBundle;
+
+@VintfStability
+parcelable VendorEffect {
+    /**
+     * Vendor data describing the haptic effect. Expected fields should be defined by the vendor.
+     *
+     * Vendors can use this as a platform extension point for experimental hardware capabilities,
+     * but they are strongly discouraged from using it as an alternative to the AOSP support for
+     * stable vibrator APIs. Implemenitng vendor-specific custom effects outside the platform APIs
+     * will hinder portability for the code and overall user experience.
+     *
+     * Vendors are encouraged to upstream new capabilities to the IVibrator surface once it has
+     * matured into a stable interface.
+     */
+    PersistableBundle vendorData;
+
+    /**
+     * The intensity of the haptic effect.
+     *
+     * This value is defined by discrete scale levels that represents the intensity of this haptic
+     * effect. This is a discrete representation of the scale parameter below.
+     */
+    EffectStrength strength = EffectStrength.MEDIUM;
+
+    /**
+     * The intensity of the haptic effect.
+     *
+     * This value is defined by continuous scale that represents the intensity of this haptic
+     * effect. The vendor implementation can follow the platform scaling function or customize the
+     * implementation to their needs. This is a continuous representation of the strength parameter
+     * above.
+     *
+     * Values in [0,1) should scale down. Values > 1 should scale up within hardware bounds.
+     */
+    float scale;
+
+    /**
+     * The dynamic scale parameter provided by the vendor vibrator controller.
+     *
+     * This value is the same provided by the vendor to the platform IVibratorControlService and
+     * should be applied on top of the effect intensity provided by the strength/scale fields.
+     * The vendor can use this to dynamically adapt the haptic effect intensity to the device state.
+     *
+     * See frameworks/hardware/interfaces/vibrator for more documentation on vendor vibrator
+     * controller, and ScaleParam for more about this scale parameter.
+     *
+     * Values in [0,1) should scale down. Values > 1 should scale up within hardware bounds.
+     */
+    float vendorScale;
+}
diff --git a/vibrator/aidl/default/Android.bp b/vibrator/aidl/default/Android.bp
index 0f342db..b25a5ba 100644
--- a/vibrator/aidl/default/Android.bp
+++ b/vibrator/aidl/default/Android.bp
@@ -15,7 +15,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.vibrator-V2-ndk",
+        "android.hardware.vibrator-V3-ndk",
     ],
     export_include_dirs: ["include"],
     srcs: [
@@ -44,12 +44,12 @@
     name: "android.hardware.vibrator-service.example",
     relative_install_path: "hw",
     init_rc: ["vibrator-default.rc"],
-    vintf_fragments: [":android.hardware.vibrator.xml"],
+    vintf_fragments: ["android.hardware.vibrator.xml"],
     vendor: true,
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.vibrator-V2-ndk",
+        "android.hardware.vibrator-V3-ndk",
     ],
     static_libs: [
         "libvibratorexampleimpl",
@@ -62,7 +62,7 @@
     host_supported: true,
     defaults: ["service_fuzzer_defaults"],
     static_libs: [
-        "android.hardware.vibrator-V2-ndk",
+        "android.hardware.vibrator-V3-ndk",
         "liblog",
         "libvibratorexampleimpl",
     ],
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index 01602ab..4f8c2b8 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -27,9 +27,12 @@
 static constexpr int32_t COMPOSE_DELAY_MAX_MS = 1000;
 static constexpr int32_t COMPOSE_SIZE_MAX = 256;
 static constexpr int32_t COMPOSE_PWLE_SIZE_MAX = 127;
+static constexpr int32_t COMPOSE_PWLE_V2_SIZE_MAX = 16;
 
 static constexpr float Q_FACTOR = 11.0;
 static constexpr int32_t COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS = 16383;
+static constexpr int32_t COMPOSE_PWLE_V2_PRIMITIVE_DURATION_MAX_MS = 1000;
+static constexpr int32_t COMPOSE_PWLE_V2_PRIMITIVE_DURATION_MIN_MS = 20;
 static constexpr float PWLE_LEVEL_MIN = 0.0;
 static constexpr float PWLE_LEVEL_MAX = 1.0;
 static constexpr float PWLE_FREQUENCY_RESOLUTION_HZ = 1.0;
@@ -39,14 +42,30 @@
 static constexpr float PWLE_BW_MAP_SIZE =
         1 + ((PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ);
 
+// Service specific error code used for vendor vibration effects.
+static constexpr int32_t ERROR_CODE_INVALID_DURATION = 1;
+
 ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
     LOG(VERBOSE) << "Vibrator reporting capabilities";
-    *_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
-                    IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL |
-                    IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS |
-                    IVibrator::CAP_ALWAYS_ON_CONTROL | IVibrator::CAP_GET_RESONANT_FREQUENCY |
-                    IVibrator::CAP_GET_Q_FACTOR | IVibrator::CAP_FREQUENCY_CONTROL |
-                    IVibrator::CAP_COMPOSE_PWLE_EFFECTS;
+    std::lock_guard lock(mMutex);
+    if (mCapabilities == 0) {
+        if (!getInterfaceVersion(&mVersion).isOk()) {
+            return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_STATE));
+        }
+        mCapabilities = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
+                        IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL |
+                        IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS |
+                        IVibrator::CAP_ALWAYS_ON_CONTROL | IVibrator::CAP_GET_RESONANT_FREQUENCY |
+                        IVibrator::CAP_GET_Q_FACTOR | IVibrator::CAP_FREQUENCY_CONTROL |
+                        IVibrator::CAP_COMPOSE_PWLE_EFFECTS;
+
+        if (mVersion >= 3) {
+            mCapabilities |= (IVibrator::CAP_PERFORM_VENDOR_EFFECTS |
+                              IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2);
+        }
+    }
+
+    *_aidl_return = mCapabilities;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -102,6 +121,47 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Vibrator::performVendorEffect(
+        const VendorEffect& effect, const std::shared_ptr<IVibratorCallback>& callback) {
+    LOG(VERBOSE) << "Vibrator perform vendor effect";
+    int32_t capabilities = 0;
+    if (!getCapabilities(&capabilities).isOk()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    if ((capabilities & IVibrator::CAP_PERFORM_VENDOR_EFFECTS) == 0) {
+        return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+    }
+    EffectStrength strength = effect.strength;
+    if (strength != EffectStrength::LIGHT && strength != EffectStrength::MEDIUM &&
+        strength != EffectStrength::STRONG) {
+        return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
+    }
+    float scale = effect.scale;
+    if (scale <= 0) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    float vendorScale = effect.vendorScale;
+    if (vendorScale <= 0) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+
+    int32_t durationMs = 0;
+    if (!effect.vendorData.getInt("DURATION_MS", &durationMs) || durationMs <= 0) {
+        return ndk::ScopedAStatus::fromServiceSpecificError(ERROR_CODE_INVALID_DURATION);
+    }
+
+    if (callback != nullptr) {
+        std::thread([callback, durationMs] {
+            LOG(VERBOSE) << "Starting perform on another thread for durationMs:" << durationMs;
+            usleep(durationMs * 1000);
+            LOG(VERBOSE) << "Notifying perform vendor effect complete";
+            callback->onComplete();
+        }).detach();
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect>* _aidl_return) {
     *_aidl_return = {Effect::CLICK, Effect::TICK};
     return ndk::ScopedAStatus::ok();
@@ -412,6 +472,122 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Vibrator::getPwleV2FrequencyToOutputAccelerationMap(
+        std::vector<PwleV2OutputMapEntry>* _aidl_return) {
+    std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
+
+    std::vector<std::pair<float, float>> frequencyToOutputAccelerationData = {
+            {30.0f, 0.01f},  {46.0f, 0.09f},  {50.0f, 0.1f},   {55.0f, 0.12f},  {62.0f, 0.66f},
+            {83.0f, 0.82f},  {85.0f, 0.85f},  {92.0f, 1.05f},  {107.0f, 1.63f}, {115.0f, 1.72f},
+            {123.0f, 1.81f}, {135.0f, 2.23f}, {144.0f, 2.47f}, {145.0f, 2.5f},  {150.0f, 3.0f},
+            {175.0f, 2.51f}, {181.0f, 2.41f}, {190.0f, 2.28f}, {200.0f, 2.08f}, {204.0f, 1.96f},
+            {205.0f, 1.9f},  {224.0f, 1.7f},  {235.0f, 1.5f},  {242.0f, 1.46f}, {253.0f, 1.41f},
+            {263.0f, 1.39f}, {65.0f, 1.38f},  {278.0f, 1.37f}, {294.0f, 1.35f}, {300.0f, 1.34f}};
+    for (const auto& entry : frequencyToOutputAccelerationData) {
+        frequencyToOutputAccelerationMap.push_back(
+                PwleV2OutputMapEntry(/*frequency=*/entry.first,
+                                     /*maxOutputAcceleration=*/entry.second));
+    }
+
+    *_aidl_return = frequencyToOutputAccelerationMap;
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getPwleV2PrimitiveDurationMaxMillis(int32_t* maxDurationMs) {
+    *maxDurationMs = COMPOSE_PWLE_V2_PRIMITIVE_DURATION_MAX_MS;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getPwleV2CompositionSizeMax(int32_t* maxSize) {
+    *maxSize = COMPOSE_PWLE_V2_SIZE_MAX;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getPwleV2PrimitiveDurationMinMillis(int32_t* minDurationMs) {
+    *minDurationMs = COMPOSE_PWLE_V2_PRIMITIVE_DURATION_MIN_MS;
+    return ndk::ScopedAStatus::ok();
+}
+
+float getPwleV2FrequencyMinHz(std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap) {
+    if (frequencyToOutputAccelerationMap.empty()) {
+        return 0.0f;
+    }
+
+    float minFrequency = frequencyToOutputAccelerationMap[0].frequencyHz;
+
+    for (const auto& entry : frequencyToOutputAccelerationMap) {
+        if (entry.frequencyHz < minFrequency) {
+            minFrequency = entry.frequencyHz;
+        }
+    }
+
+    return minFrequency;
+}
+
+float getPwleV2FrequencyMaxHz(std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap) {
+    if (frequencyToOutputAccelerationMap.empty()) {
+        return 0.0f;
+    }
+
+    float maxFrequency = frequencyToOutputAccelerationMap[0].frequencyHz;
+
+    for (const auto& entry : frequencyToOutputAccelerationMap) {
+        if (entry.frequencyHz > maxFrequency) {
+            maxFrequency = entry.frequencyHz;
+        }
+    }
+
+    return maxFrequency;
+}
+
+ndk::ScopedAStatus Vibrator::composePwleV2(const std::vector<PwleV2Primitive>& composite,
+                                           const std::shared_ptr<IVibratorCallback>& callback) {
+    int32_t capabilities = 0;
+    if (!getCapabilities(&capabilities).isOk()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2) == 0) {
+        return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+    }
+
+    int compositionSizeMax;
+    getPwleV2CompositionSizeMax(&compositionSizeMax);
+    if (composite.size() <= 0 || composite.size() > compositionSizeMax) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+
+    int32_t totalEffectDuration = 0;
+    std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
+    getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap);
+    float minFrequency = getPwleV2FrequencyMinHz(frequencyToOutputAccelerationMap);
+    float maxFrequency = getPwleV2FrequencyMaxHz(frequencyToOutputAccelerationMap);
+
+    for (auto& e : composite) {
+        if (e.timeMillis < 0.0f || e.timeMillis > COMPOSE_PWLE_V2_PRIMITIVE_DURATION_MAX_MS) {
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+        if (e.amplitude < 0.0f || e.amplitude > 1.0f) {
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+        if (e.frequencyHz < minFrequency || e.frequencyHz > maxFrequency) {
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+        totalEffectDuration += e.timeMillis;
+    }
+
+    std::thread([totalEffectDuration, callback] {
+        LOG(VERBOSE) << "Starting composePwleV2 on another thread";
+        usleep(totalEffectDuration * 1000);
+        if (callback != nullptr) {
+            LOG(VERBOSE) << "Notifying compose PWLE V2 complete";
+            callback->onComplete();
+        }
+    }).detach();
+
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace vibrator
 }  // namespace hardware
 }  // namespace android
diff --git a/vibrator/aidl/default/android.hardware.vibrator.xml b/vibrator/aidl/default/android.hardware.vibrator.xml
index b5bd3dd..b730046 100644
--- a/vibrator/aidl/default/android.hardware.vibrator.xml
+++ b/vibrator/aidl/default/android.hardware.vibrator.xml
@@ -1,12 +1,12 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.vibrator</name>
-        <version>2</version>
+        <version>3</version>
         <fqname>IVibrator/default</fqname>
     </hal>
     <hal format="aidl">
         <name>android.hardware.vibrator</name>
-        <version>2</version>
+        <version>3</version>
         <fqname>IVibratorManager/default</fqname>
     </hal>
 </manifest>
diff --git a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
index 4203bf2..28bc763 100644
--- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
+++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <aidl/android/hardware/vibrator/BnVibrator.h>
+#include <android-base/thread_annotations.h>
 
 namespace aidl {
 namespace android {
@@ -31,6 +32,9 @@
     ndk::ScopedAStatus perform(Effect effect, EffectStrength strength,
                                const std::shared_ptr<IVibratorCallback>& callback,
                                int32_t* _aidl_return) override;
+    ndk::ScopedAStatus performVendorEffect(
+            const VendorEffect& effect,
+            const std::shared_ptr<IVibratorCallback>& callback) override;
     ndk::ScopedAStatus getSupportedEffects(std::vector<Effect>* _aidl_return) override;
     ndk::ScopedAStatus setAmplitude(float amplitude) override;
     ndk::ScopedAStatus setExternalControl(bool enabled) override;
@@ -54,7 +58,18 @@
     ndk::ScopedAStatus getSupportedBraking(std::vector<Braking>* supported) override;
     ndk::ScopedAStatus composePwle(const std::vector<PrimitivePwle> &composite,
                                    const std::shared_ptr<IVibratorCallback> &callback) override;
+    ndk::ScopedAStatus getPwleV2FrequencyToOutputAccelerationMap(
+            std::vector<PwleV2OutputMapEntry>* _aidl_return) override;
+    ndk::ScopedAStatus getPwleV2PrimitiveDurationMaxMillis(int32_t* maxDurationMs) override;
+    ndk::ScopedAStatus getPwleV2PrimitiveDurationMinMillis(int32_t* minDurationMs) override;
+    ndk::ScopedAStatus getPwleV2CompositionSizeMax(int32_t* maxSize) override;
+    ndk::ScopedAStatus composePwleV2(const std::vector<PwleV2Primitive>& composite,
+                                     const std::shared_ptr<IVibratorCallback>& callback) override;
 
+  private:
+    mutable std::mutex mMutex;
+    int32_t mVersion GUARDED_BY(mMutex) = 0;  // current Hal version
+    int32_t mCapabilities GUARDED_BY(mMutex) = 0;
 };
 
 }  // namespace vibrator
diff --git a/vibrator/aidl/vts/Android.bp b/vibrator/aidl/vts/Android.bp
index b6d2fb2..a48bb2e 100644
--- a/vibrator/aidl/vts/Android.bp
+++ b/vibrator/aidl/vts/Android.bp
@@ -17,10 +17,10 @@
     tidy_timeout_srcs: ["VtsHalVibratorTargetTest.cpp"],
     srcs: ["VtsHalVibratorTargetTest.cpp"],
     shared_libs: [
-        "libbinder",
+        "libbinder_ndk",
     ],
     static_libs: [
-        "android.hardware.vibrator-V2-cpp",
+        "android.hardware.vibrator-V3-ndk",
     ],
     test_suites: [
         "general-tests",
@@ -36,10 +36,10 @@
     ],
     srcs: ["VtsHalVibratorManagerTargetTest.cpp"],
     shared_libs: [
-        "libbinder",
+        "libbinder_ndk",
     ],
     static_libs: [
-        "android.hardware.vibrator-V2-cpp",
+        "android.hardware.vibrator-V3-ndk",
     ],
     test_suites: [
         "general-tests",
diff --git a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
index e8ed26a..3c2a360 100644
--- a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
@@ -15,42 +15,40 @@
  */
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
+#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+#include <aidl/android/hardware/vibrator/IVibratorManager.h>
 
-#include <android/hardware/vibrator/BnVibratorCallback.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <android/hardware/vibrator/IVibratorManager.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
 
 #include <cmath>
 #include <future>
 
-using android::ProcessState;
-using android::sp;
-using android::String16;
-using android::binder::Status;
-using android::hardware::vibrator::BnVibratorCallback;
-using android::hardware::vibrator::CompositeEffect;
-using android::hardware::vibrator::CompositePrimitive;
-using android::hardware::vibrator::Effect;
-using android::hardware::vibrator::EffectStrength;
-using android::hardware::vibrator::IVibrator;
-using android::hardware::vibrator::IVibratorManager;
+#include "test_utils.h"
+
+using aidl::android::hardware::vibrator::BnVibratorCallback;
+using aidl::android::hardware::vibrator::CompositeEffect;
+using aidl::android::hardware::vibrator::CompositePrimitive;
+using aidl::android::hardware::vibrator::Effect;
+using aidl::android::hardware::vibrator::EffectStrength;
+using aidl::android::hardware::vibrator::IVibrator;
+using aidl::android::hardware::vibrator::IVibratorManager;
 using std::chrono::high_resolution_clock;
 
-const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
-                                   android::enum_range<Effect>().end()};
-const std::vector<EffectStrength> kEffectStrengths{android::enum_range<EffectStrength>().begin(),
-                                                   android::enum_range<EffectStrength>().end()};
-const std::vector<CompositePrimitive> kPrimitives{android::enum_range<CompositePrimitive>().begin(),
-                                                  android::enum_range<CompositePrimitive>().end()};
+const std::vector<Effect> kEffects{ndk::enum_range<Effect>().begin(),
+                                   ndk::enum_range<Effect>().end()};
+const std::vector<EffectStrength> kEffectStrengths{ndk::enum_range<EffectStrength>().begin(),
+                                                   ndk::enum_range<EffectStrength>().end()};
+const std::vector<CompositePrimitive> kPrimitives{ndk::enum_range<CompositePrimitive>().begin(),
+                                                  ndk::enum_range<CompositePrimitive>().end()};
 
 class CompletionCallback : public BnVibratorCallback {
   public:
     CompletionCallback(const std::function<void()>& callback) : mCallback(callback) {}
-    Status onComplete() override {
+    ndk::ScopedAStatus onComplete() override {
         mCallback();
-        return Status::ok();
+        return ndk::ScopedAStatus::ok();
     }
 
   private:
@@ -60,55 +58,50 @@
 class VibratorAidl : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
-        manager = android::waitForDeclaredService<IVibratorManager>(String16(GetParam().c_str()));
+        auto serviceName = GetParam().c_str();
+        manager = IVibratorManager::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(serviceName)));
         ASSERT_NE(manager, nullptr);
-        ASSERT_TRUE(manager->getCapabilities(&capabilities).isOk());
-        EXPECT_TRUE(manager->getVibratorIds(&vibratorIds).isOk());
+        EXPECT_OK(manager->getCapabilities(&capabilities));
+        EXPECT_OK(manager->getVibratorIds(&vibratorIds));
     }
 
-    sp<IVibratorManager> manager;
+    std::shared_ptr<IVibratorManager> manager;
     int32_t capabilities;
     std::vector<int32_t> vibratorIds;
 };
 
-inline bool isUnknownOrUnsupported(Status status) {
-    return status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
-           status.transactionError() == android::UNKNOWN_TRANSACTION;
-}
-
 TEST_P(VibratorAidl, ValidateExistingVibrators) {
-    sp<IVibrator> vibrator;
-    for (auto& id : vibratorIds) {
-        EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+    std::shared_ptr<IVibrator> vibrator;
+    for (int32_t id : vibratorIds) {
+        EXPECT_OK(manager->getVibrator(id, &vibrator));
         ASSERT_NE(vibrator, nullptr);
     }
 }
 
 TEST_P(VibratorAidl, GetVibratorWithInvalidId) {
     int32_t invalidId = *max_element(vibratorIds.begin(), vibratorIds.end()) + 1;
-    sp<IVibrator> vibrator;
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-              manager->getVibrator(invalidId, &vibrator).exceptionCode());
+    std::shared_ptr<IVibrator> vibrator;
+    EXPECT_ILLEGAL_ARGUMENT(manager->getVibrator(invalidId, &vibrator));
     ASSERT_EQ(vibrator, nullptr);
 }
 
 TEST_P(VibratorAidl, ValidatePrepareSyncedExistingVibrators) {
     if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
     if (vibratorIds.empty()) return;
-    EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-    EXPECT_TRUE(manager->cancelSynced().isOk());
+    EXPECT_OK(manager->prepareSynced(vibratorIds));
+    EXPECT_OK(manager->cancelSynced());
 }
 
 TEST_P(VibratorAidl, PrepareSyncedEmptySetIsInvalid) {
     if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
     std::vector<int32_t> emptyIds;
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, manager->prepareSynced(emptyIds).exceptionCode());
+    EXPECT_ILLEGAL_ARGUMENT(manager->prepareSynced(emptyIds));
 }
 
 TEST_P(VibratorAidl, PrepareSyncedNotSupported) {
     if (!(capabilities & IVibratorManager::CAP_SYNC)) {
-        Status status = manager->prepareSynced(vibratorIds);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(manager->prepareSynced(vibratorIds));
     }
 }
 
@@ -117,15 +110,14 @@
     if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
     if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) {
         uint32_t durationMs = 250;
-        EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-        sp<IVibrator> vibrator;
-        for (auto& id : vibratorIds) {
-            EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+        EXPECT_OK(manager->prepareSynced(vibratorIds));
+        std::shared_ptr<IVibrator> vibrator;
+        for (int32_t id : vibratorIds) {
+            EXPECT_OK(manager->getVibrator(id, &vibrator));
             ASSERT_NE(vibrator, nullptr);
-            Status status = vibrator->on(durationMs, nullptr);
-            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->on(durationMs, nullptr));
         }
-        EXPECT_TRUE(manager->cancelSynced().isOk());
+        EXPECT_OK(manager->cancelSynced());
     }
 }
 
@@ -133,16 +125,16 @@
     if (vibratorIds.empty()) return;
     if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
     if (!(capabilities & IVibratorManager::CAP_PREPARE_ON)) {
-        EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-        sp<IVibrator> vibrator;
-        for (auto& id : vibratorIds) {
-            EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+        EXPECT_OK(manager->prepareSynced(vibratorIds));
+        std::shared_ptr<IVibrator> vibrator;
+        for (int32_t id : vibratorIds) {
+            EXPECT_OK(manager->getVibrator(id, &vibrator));
             ASSERT_NE(vibrator, nullptr);
             int32_t lengthMs = 0;
-            Status status = vibrator->perform(kEffects[0], kEffectStrengths[0], nullptr, &lengthMs);
-            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(
+                    vibrator->perform(kEffects[0], kEffectStrengths[0], nullptr, &lengthMs));
         }
-        EXPECT_TRUE(manager->cancelSynced().isOk());
+        EXPECT_OK(manager->cancelSynced());
     }
 }
 
@@ -157,15 +149,14 @@
         effect.scale = 1.0f;
         composite.emplace_back(effect);
 
-        EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-        sp<IVibrator> vibrator;
-        for (auto& id : vibratorIds) {
-            EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+        EXPECT_OK(manager->prepareSynced(vibratorIds));
+        std::shared_ptr<IVibrator> vibrator;
+        for (int32_t id : vibratorIds) {
+            EXPECT_OK(manager->getVibrator(id, &vibrator));
             ASSERT_NE(vibrator, nullptr);
-            Status status = vibrator->compose(composite, nullptr);
-            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->compose(composite, nullptr));
         }
-        EXPECT_TRUE(manager->cancelSynced().isOk());
+        EXPECT_OK(manager->cancelSynced());
     }
 }
 
@@ -177,51 +168,58 @@
 
     std::promise<void> completionPromise;
     std::future<void> completionFuture{completionPromise.get_future()};
-    sp<CompletionCallback> callback =
-            new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+    auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+            [&completionPromise] { completionPromise.set_value(); });
     uint32_t durationMs = 250;
     std::chrono::milliseconds timeout{durationMs * 2};
 
-    EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-    sp<IVibrator> vibrator;
-    for (auto& id : vibratorIds) {
-        EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
+    EXPECT_OK(manager->prepareSynced(vibratorIds));
+    std::shared_ptr<IVibrator> vibrator;
+    for (int32_t id : vibratorIds) {
+        EXPECT_OK(manager->getVibrator(id, &vibrator));
         ASSERT_NE(vibrator, nullptr);
-        EXPECT_TRUE(vibrator->on(durationMs, nullptr).isOk());
+        EXPECT_OK(vibrator->on(durationMs, nullptr));
     }
 
-    EXPECT_TRUE(manager->triggerSynced(callback).isOk());
+    EXPECT_OK(manager->triggerSynced(callback));
     EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
-    EXPECT_TRUE(manager->cancelSynced().isOk());
+    EXPECT_OK(manager->cancelSynced());
 }
 
 TEST_P(VibratorAidl, TriggerSyncNotSupported) {
     if (!(capabilities & IVibratorManager::CAP_SYNC)) {
-        Status status = manager->triggerSynced(nullptr);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(manager->triggerSynced(nullptr));
     }
 }
 
 TEST_P(VibratorAidl, TriggerCallbackNotSupported) {
     if (!(capabilities & IVibratorManager::CAP_SYNC)) return;
     if (!(capabilities & IVibratorManager::CAP_TRIGGER_CALLBACK)) {
-        sp<CompletionCallback> callback = new CompletionCallback([] {});
-        EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-        Status status = manager->triggerSynced(callback);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
-        EXPECT_TRUE(manager->cancelSynced().isOk());
+        auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
+        EXPECT_OK(manager->prepareSynced(vibratorIds));
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(manager->triggerSynced(callback));
+        EXPECT_OK(manager->cancelSynced());
     }
 }
 
+std::vector<std::string> FindVibratorManagerNames() {
+    std::vector<std::string> names;
+    constexpr auto callback = [](const char* instance, void* context) {
+        std::string fullName = std::string(IVibratorManager::descriptor) + "/" + instance;
+        static_cast<std::vector<std::string>*>(context)->emplace_back(fullName);
+    };
+    AServiceManager_forEachDeclaredInstance(IVibratorManager::descriptor,
+                                            static_cast<void*>(&names), callback);
+    return names;
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VibratorAidl);
-INSTANTIATE_TEST_SUITE_P(
-        Vibrator, VibratorAidl,
-        testing::ValuesIn(android::getAidlHalInstanceNames(IVibratorManager::descriptor)),
-        android::PrintInstanceNameToString);
+INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl, testing::ValuesIn(FindVibratorManagerNames()),
+                         android::PrintInstanceNameToString);
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
-    ProcessState::self()->setThreadPoolMaxThreadCount(1);
-    ProcessState::self()->startThreadPool();
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
 }
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index db474d6..bc017ae 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -15,38 +15,51 @@
  */
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
-#include <android/hardware/vibrator/BnVibratorCallback.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <android/hardware/vibrator/IVibratorManager.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
+#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+#include <aidl/android/hardware/vibrator/IVibratorManager.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/persistable_bundle_aidl.h>
 
 #include <cmath>
+#include <cstdlib>
+#include <ctime>
 #include <future>
+#include <iomanip>
+#include <iostream>
+#include <random>
 
-using android::ProcessState;
-using android::sp;
-using android::String16;
-using android::binder::Status;
-using android::hardware::vibrator::ActivePwle;
-using android::hardware::vibrator::BnVibratorCallback;
-using android::hardware::vibrator::Braking;
-using android::hardware::vibrator::BrakingPwle;
-using android::hardware::vibrator::CompositeEffect;
-using android::hardware::vibrator::CompositePrimitive;
-using android::hardware::vibrator::Effect;
-using android::hardware::vibrator::EffectStrength;
-using android::hardware::vibrator::IVibrator;
-using android::hardware::vibrator::IVibratorManager;
-using android::hardware::vibrator::PrimitivePwle;
+#include "persistable_bundle_utils.h"
+#include "pwle_v2_utils.h"
+#include "test_utils.h"
+
+using aidl::android::hardware::vibrator::ActivePwle;
+using aidl::android::hardware::vibrator::BnVibratorCallback;
+using aidl::android::hardware::vibrator::Braking;
+using aidl::android::hardware::vibrator::BrakingPwle;
+using aidl::android::hardware::vibrator::CompositeEffect;
+using aidl::android::hardware::vibrator::CompositePrimitive;
+using aidl::android::hardware::vibrator::Effect;
+using aidl::android::hardware::vibrator::EffectStrength;
+using aidl::android::hardware::vibrator::IVibrator;
+using aidl::android::hardware::vibrator::IVibratorManager;
+using aidl::android::hardware::vibrator::PrimitivePwle;
+using aidl::android::hardware::vibrator::PwleV2OutputMapEntry;
+using aidl::android::hardware::vibrator::PwleV2Primitive;
+using aidl::android::hardware::vibrator::VendorEffect;
+using aidl::android::os::PersistableBundle;
 using std::chrono::high_resolution_clock;
 
 using namespace ::std::chrono_literals;
 
-const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
-                                   android::enum_range<Effect>().end()};
-const std::vector<EffectStrength> kEffectStrengths{android::enum_range<EffectStrength>().begin(),
-                                                   android::enum_range<EffectStrength>().end()};
+namespace pwle_v2_utils = aidl::android::hardware::vibrator::testing::pwlev2;
+
+const std::vector<Effect> kEffects{ndk::enum_range<Effect>().begin(),
+                                   ndk::enum_range<Effect>().end()};
+const std::vector<EffectStrength> kEffectStrengths{ndk::enum_range<EffectStrength>().begin(),
+                                                   ndk::enum_range<EffectStrength>().end()};
 
 const std::vector<Effect> kInvalidEffects = {
     static_cast<Effect>(static_cast<int32_t>(kEffects.front()) - 1),
@@ -59,8 +72,7 @@
 };
 
 const std::vector<CompositePrimitive> kCompositePrimitives{
-    android::enum_range<CompositePrimitive>().begin(),
-    android::enum_range<CompositePrimitive>().end()};
+        ndk::enum_range<CompositePrimitive>().begin(), ndk::enum_range<CompositePrimitive>().end()};
 
 const std::vector<CompositePrimitive> kRequiredPrimitives = {
         CompositePrimitive::CLICK,      CompositePrimitive::LIGHT_TICK,
@@ -74,14 +86,39 @@
 };
 
 // Timeout to wait for vibration callback completion.
-static constexpr auto VIBRATION_CALLBACK_TIMEOUT = 100ms;
+static constexpr std::chrono::milliseconds VIBRATION_CALLBACK_TIMEOUT = 100ms;
+
+static constexpr int32_t VENDOR_EFFECTS_MIN_VERSION = 3;
+static constexpr int32_t PWLE_V2_MIN_VERSION = 3;
+
+static std::vector<std::string> findVibratorManagerNames() {
+    std::vector<std::string> names;
+    constexpr auto callback = [](const char* instance, void* context) {
+        auto fullName = std::string(IVibratorManager::descriptor) + "/" + instance;
+        static_cast<std::vector<std::string>*>(context)->emplace_back(fullName);
+    };
+    AServiceManager_forEachDeclaredInstance(IVibratorManager::descriptor,
+                                            static_cast<void*>(&names), callback);
+    return names;
+}
+
+static std::vector<std::string> findUnmanagedVibratorNames() {
+    std::vector<std::string> names;
+    constexpr auto callback = [](const char* instance, void* context) {
+        auto fullName = std::string(IVibrator::descriptor) + "/" + instance;
+        static_cast<std::vector<std::string>*>(context)->emplace_back(fullName);
+    };
+    AServiceManager_forEachDeclaredInstance(IVibrator::descriptor, static_cast<void*>(&names),
+                                            callback);
+    return names;
+}
 
 class CompletionCallback : public BnVibratorCallback {
   public:
     CompletionCallback(const std::function<void()> &callback) : mCallback(callback) {}
-    Status onComplete() override {
+    ndk::ScopedAStatus onComplete() override {
         mCallback();
-        return Status::ok();
+        return ndk::ScopedAStatus::ok();
     }
 
   private:
@@ -93,88 +130,89 @@
     virtual void SetUp() override {
         int32_t managerIdx = std::get<0>(GetParam());
         int32_t vibratorId = std::get<1>(GetParam());
-        auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
 
         if (managerIdx < 0) {
             // Testing a unmanaged vibrator, using vibratorId as index from registered HALs
-            auto vibratorAidlNames = android::getAidlHalInstanceNames(IVibrator::descriptor);
-            ASSERT_LT(vibratorId, vibratorAidlNames.size());
-            auto vibratorName = String16(vibratorAidlNames[vibratorId].c_str());
-            vibrator = android::waitForDeclaredService<IVibrator>(vibratorName);
+            std::vector<std::string> vibratorNames = findUnmanagedVibratorNames();
+            ASSERT_LT(vibratorId, vibratorNames.size());
+            vibrator = IVibrator::fromBinder(ndk::SpAIBinder(
+                    AServiceManager_waitForService(vibratorNames[vibratorId].c_str())));
         } else {
             // Testing a managed vibrator, using vibratorId to retrieve it from the manager
-            ASSERT_LT(managerIdx, managerAidlNames.size());
-            auto managerName = String16(managerAidlNames[managerIdx].c_str());
-            auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
-            auto vibratorResult = vibratorManager->getVibrator(vibratorId, &vibrator);
-            ASSERT_TRUE(vibratorResult.isOk());
+            std::vector<std::string> managerNames = findVibratorManagerNames();
+            ASSERT_LT(managerIdx, managerNames.size());
+            auto vibratorManager = IVibratorManager::fromBinder(ndk::SpAIBinder(
+                    AServiceManager_waitForService(managerNames[managerIdx].c_str())));
+            EXPECT_OK(vibratorManager->getVibrator(vibratorId, &vibrator))
+                    << "\n  For vibrator id: " << vibratorId;
         }
 
         ASSERT_NE(vibrator, nullptr);
-        ASSERT_TRUE(vibrator->getCapabilities(&capabilities).isOk());
+        EXPECT_OK(vibrator->getInterfaceVersion(&version));
+        EXPECT_OK(vibrator->getCapabilities(&capabilities));
     }
 
     virtual void TearDown() override {
         // Reset vibrator state between tests.
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_OK(vibrator->off());
     }
 
-    sp<IVibrator> vibrator;
+    std::shared_ptr<IVibrator> vibrator;
+    int32_t version;
     int32_t capabilities;
 };
 
-inline bool isUnknownOrUnsupported(Status status) {
-    return status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
-           status.transactionError() == android::UNKNOWN_TRANSACTION;
-}
-
-static float getResonantFrequencyHz(sp<IVibrator> vibrator, int32_t capabilities) {
+static float getResonantFrequencyHz(const std::shared_ptr<IVibrator>& vibrator,
+                                    int32_t capabilities) {
     float resonantFrequencyHz;
-    Status status = vibrator->getResonantFrequency(&resonantFrequencyHz);
+    ndk::ScopedAStatus status = vibrator->getResonantFrequency(&resonantFrequencyHz);
     if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
+        EXPECT_OK(std::move(status));
         EXPECT_GT(resonantFrequencyHz, 0);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
     return resonantFrequencyHz;
 }
 
-static float getFrequencyResolutionHz(sp<IVibrator> vibrator, int32_t capabilities) {
+static float getFrequencyResolutionHz(const std::shared_ptr<IVibrator>& vibrator,
+                                      int32_t capabilities) {
     float freqResolutionHz;
-    Status status = vibrator->getFrequencyResolution(&freqResolutionHz);
+    ndk::ScopedAStatus status = vibrator->getFrequencyResolution(&freqResolutionHz);
     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+        EXPECT_OK(std::move(status));
         EXPECT_GT(freqResolutionHz, 0);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
     return freqResolutionHz;
 }
 
-static float getFrequencyMinimumHz(sp<IVibrator> vibrator, int32_t capabilities) {
+static float getFrequencyMinimumHz(const std::shared_ptr<IVibrator>& vibrator,
+                                   int32_t capabilities) {
     float freqMinimumHz;
-    Status status = vibrator->getFrequencyMinimum(&freqMinimumHz);
+    ndk::ScopedAStatus status = vibrator->getFrequencyMinimum(&freqMinimumHz);
     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+        EXPECT_OK(std::move(status));
 
         float resonantFrequencyHz = getResonantFrequencyHz(vibrator, capabilities);
 
         EXPECT_GT(freqMinimumHz, 0);
         EXPECT_LE(freqMinimumHz, resonantFrequencyHz);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
     return freqMinimumHz;
 }
 
-static float getFrequencyMaximumHz(sp<IVibrator> vibrator, int32_t capabilities) {
+static float getFrequencyMaximumHz(const std::shared_ptr<IVibrator>& vibrator,
+                                   int32_t capabilities) {
     std::vector<float> bandwidthAmplitudeMap;
-    Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
+    ndk::ScopedAStatus status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+        EXPECT_OK(std::move(status));
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 
     float freqMaximumHz = ((bandwidthAmplitudeMap.size() - 1) *
@@ -191,7 +229,8 @@
     return 1.0;
 }
 
-static ActivePwle composeValidActivePwle(sp<IVibrator> vibrator, int32_t capabilities) {
+static ActivePwle composeValidActivePwle(const std::shared_ptr<IVibrator>& vibrator,
+                                         int32_t capabilities) {
     float frequencyHz;
     if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
         frequencyHz = getResonantFrequencyHz(vibrator, capabilities);
@@ -212,9 +251,9 @@
 }
 
 TEST_P(VibratorAidl, OnThenOffBeforeTimeout) {
-    EXPECT_TRUE(vibrator->on(2000, nullptr /*callback*/).isOk());
+    EXPECT_OK(vibrator->on(2000, nullptr /*callback*/));
     sleep(1);
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->off());
 }
 
 TEST_P(VibratorAidl, OnWithCallback) {
@@ -223,26 +262,25 @@
 
     std::promise<void> completionPromise;
     std::future<void> completionFuture{completionPromise.get_future()};
-    sp<CompletionCallback> callback =
-        new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+    auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+            [&completionPromise] { completionPromise.set_value(); });
     uint32_t durationMs = 250;
     auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT;
-    EXPECT_TRUE(vibrator->on(durationMs, callback).isOk());
+    EXPECT_OK(vibrator->on(durationMs, callback));
     EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->off());
 }
 
 TEST_P(VibratorAidl, OnCallbackNotSupported) {
     if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) {
-        sp<CompletionCallback> callback = new CompletionCallback([] {});
-        Status status = vibrator->on(250, callback);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->on(250, callback));
     }
 }
 
 TEST_P(VibratorAidl, ValidateEffect) {
     std::vector<Effect> supported;
-    ASSERT_TRUE(vibrator->getSupportedEffects(&supported).isOk());
+    EXPECT_OK(vibrator->getSupportedEffects(&supported));
 
     for (Effect effect : kEffects) {
         bool isEffectSupported =
@@ -250,15 +288,18 @@
 
         for (EffectStrength strength : kEffectStrengths) {
             int32_t lengthMs = 0;
-            Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
+            ndk::ScopedAStatus status =
+                    vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
 
             if (isEffectSupported) {
-                EXPECT_TRUE(status.isOk()) << toString(effect) << " " << toString(strength);
+                EXPECT_OK(std::move(status))
+                        << "\n  For effect: " << toString(effect) << " " << toString(strength);
                 EXPECT_GT(lengthMs, 0);
                 usleep(lengthMs * 1000);
+                EXPECT_OK(vibrator->off());
             } else {
-                EXPECT_TRUE(isUnknownOrUnsupported(status))
-                        << status << " " << toString(effect) << " " << toString(strength);
+                EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status))
+                        << "\n  For effect: " << toString(effect) << " " << toString(strength);
             }
         }
     }
@@ -269,7 +310,7 @@
         return;
 
     std::vector<Effect> supported;
-    ASSERT_TRUE(vibrator->getSupportedEffects(&supported).isOk());
+    EXPECT_OK(vibrator->getSupportedEffects(&supported));
 
     for (Effect effect : kEffects) {
         bool isEffectSupported =
@@ -278,25 +319,26 @@
         for (EffectStrength strength : kEffectStrengths) {
             std::promise<void> completionPromise;
             std::future<void> completionFuture{completionPromise.get_future()};
-            sp<CompletionCallback> callback =
-                new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+            auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+                    [&completionPromise] { completionPromise.set_value(); });
             int lengthMs = 0;
-            Status status = vibrator->perform(effect, strength, callback, &lengthMs);
+            ndk::ScopedAStatus status = vibrator->perform(effect, strength, callback, &lengthMs);
 
             if (isEffectSupported) {
-                EXPECT_TRUE(status.isOk());
+                EXPECT_OK(std::move(status))
+                        << "\n  For effect: " << toString(effect) << " " << toString(strength);
                 EXPECT_GT(lengthMs, 0);
             } else {
-                EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+                EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status))
+                        << "\n  For effect: " << toString(effect) << " " << toString(strength);
             }
 
-            if (!status.isOk())
-                continue;
+            if (lengthMs <= 0) continue;
 
             auto timeout = std::chrono::milliseconds(lengthMs) + VIBRATION_CALLBACK_TIMEOUT;
             EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
 
-            EXPECT_TRUE(vibrator->off().isOk());
+            EXPECT_OK(vibrator->off());
         }
     }
 }
@@ -307,10 +349,10 @@
 
     for (Effect effect : kEffects) {
         for (EffectStrength strength : kEffectStrengths) {
-            sp<CompletionCallback> callback = new CompletionCallback([] {});
+            auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
             int lengthMs;
-            Status status = vibrator->perform(effect, strength, callback, &lengthMs);
-            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->perform(effect, strength, callback, &lengthMs))
+                    << "\n  For effect: " << toString(effect) << " " << toString(strength);
         }
     }
 }
@@ -319,53 +361,182 @@
     for (Effect effect : kInvalidEffects) {
         for (EffectStrength strength : kEffectStrengths) {
             int32_t lengthMs;
-            Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
-            EXPECT_TRUE(isUnknownOrUnsupported(status))
-                    << status << toString(effect) << " " << toString(strength);
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(
+                    vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs))
+                    << "\n  For effect: " << toString(effect) << " " << toString(strength);
         }
     }
     for (Effect effect : kEffects) {
         for (EffectStrength strength : kInvalidEffectStrengths) {
             int32_t lengthMs;
-            Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
-            EXPECT_TRUE(isUnknownOrUnsupported(status))
-                    << status << " " << toString(effect) << " " << toString(strength);
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(
+                    vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs))
+                    << "\n  For effect: " << toString(effect) << " " << toString(strength);
         }
     }
 }
 
+TEST_P(VibratorAidl, PerformVendorEffectSupported) {
+    if ((capabilities & IVibrator::CAP_PERFORM_VENDOR_EFFECTS) == 0) return;
+
+    float scale = 0.0f;
+    float vendorScale = 0.0f;
+    for (EffectStrength strength : kEffectStrengths) {
+        PersistableBundle vendorData;
+        ::aidl::android::hardware::vibrator::testing::fillBasicData(&vendorData);
+
+        PersistableBundle nestedData;
+        ::aidl::android::hardware::vibrator::testing::fillBasicData(&nestedData);
+        vendorData.putPersistableBundle("test_nested_bundle", nestedData);
+
+        VendorEffect effect;
+        effect.vendorData = vendorData;
+        effect.strength = strength;
+        effect.scale = scale;
+        effect.vendorScale = vendorScale;
+        scale += 0.5f;
+        vendorScale += 0.2f;
+
+        auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
+        ndk::ScopedAStatus status = vibrator->performVendorEffect(effect, callback);
+
+        // No expectations on the actual status, the effect might be refused with illegal argument
+        // or the vendor might return a service-specific error code.
+        EXPECT_TRUE(status.getExceptionCode() != EX_UNSUPPORTED_OPERATION &&
+                    status.getStatus() != STATUS_UNKNOWN_TRANSACTION)
+                << status << "\n For vendor effect with strength" << toString(strength)
+                << " and scale " << effect.scale;
+
+        if (status.isOk()) {
+            // Generic vendor data should not trigger vibrations, but if it does trigger one
+            // then we make sure the vibrator is reset by triggering off().
+            EXPECT_OK(vibrator->off());
+        }
+    }
+}
+
+TEST_P(VibratorAidl, PerformVendorEffectStability) {
+    if ((capabilities & IVibrator::CAP_PERFORM_VENDOR_EFFECTS) == 0) return;
+
+    // Run some iterations of performVendorEffect with randomized vendor data to check basic
+    // stability of the implementation.
+    uint8_t iterations = 200;
+
+    for (EffectStrength strength : kEffectStrengths) {
+        float scale = 0.5f;
+        float vendorScale = 0.2f;
+        for (uint8_t i = 0; i < iterations; i++) {
+            PersistableBundle vendorData;
+            ::aidl::android::hardware::vibrator::testing::fillRandomData(&vendorData);
+
+            VendorEffect effect;
+            effect.vendorData = vendorData;
+            effect.strength = strength;
+            effect.scale = scale;
+            effect.vendorScale = vendorScale;
+            scale *= 2;
+            vendorScale *= 1.5f;
+
+            auto callback = ndk::SharedRefBase::make<CompletionCallback>([] {});
+            ndk::ScopedAStatus status = vibrator->performVendorEffect(effect, callback);
+
+            // No expectations on the actual status, the effect might be refused with illegal
+            // argument or the vendor might return a service-specific error code.
+            EXPECT_TRUE(status.getExceptionCode() != EX_UNSUPPORTED_OPERATION &&
+                        status.getStatus() != STATUS_UNKNOWN_TRANSACTION)
+                    << status << "\n For random vendor effect with strength " << toString(strength)
+                    << " and scale " << effect.scale;
+
+            if (status.isOk()) {
+                // Random vendor data should not trigger vibrations, but if it does trigger one
+                // then we make sure the vibrator is reset by triggering off().
+                EXPECT_OK(vibrator->off());
+            }
+        }
+    }
+}
+
+TEST_P(VibratorAidl, PerformVendorEffectEmptyVendorData) {
+    if ((capabilities & IVibrator::CAP_PERFORM_VENDOR_EFFECTS) == 0) return;
+
+    for (EffectStrength strength : kEffectStrengths) {
+        VendorEffect effect;
+        effect.strength = strength;
+        effect.scale = 1.0f;
+        effect.vendorScale = 1.0f;
+
+        ndk::ScopedAStatus status = vibrator->performVendorEffect(effect, nullptr /*callback*/);
+
+        EXPECT_TRUE(status.getExceptionCode() == EX_SERVICE_SPECIFIC)
+                << status << "\n For vendor effect with strength " << toString(strength)
+                << " and scale " << effect.scale;
+    }
+}
+
+TEST_P(VibratorAidl, PerformVendorEffectInvalidScale) {
+    if ((capabilities & IVibrator::CAP_PERFORM_VENDOR_EFFECTS) == 0) return;
+
+    VendorEffect effect;
+    effect.strength = EffectStrength::MEDIUM;
+
+    effect.scale = -1.0f;
+    effect.vendorScale = 1.0f;
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->performVendorEffect(effect, nullptr /*callback*/));
+
+    effect.scale = 1.0f;
+    effect.vendorScale = -1.0f;
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->performVendorEffect(effect, nullptr /*callback*/));
+}
+
+TEST_P(VibratorAidl, PerformVendorEffectUnsupported) {
+    if (version < VENDOR_EFFECTS_MIN_VERSION) {
+        EXPECT_EQ(capabilities & IVibrator::CAP_PERFORM_VENDOR_EFFECTS, 0)
+                << "Vibrator version " << version << " should not report vendor effects capability";
+    }
+    if (capabilities & IVibrator::CAP_PERFORM_VENDOR_EFFECTS) return;
+
+    for (EffectStrength strength : kEffectStrengths) {
+        VendorEffect effect;
+        effect.strength = strength;
+        effect.scale = 1.0f;
+        effect.vendorScale = 1.0f;
+
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->performVendorEffect(effect, nullptr /*callback*/))
+                << "\n  For vendor effect with strength " << toString(strength);
+    }
+}
+
 TEST_P(VibratorAidl, ChangeVibrationAmplitude) {
     if (capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) {
-        EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(0.1f).exceptionCode());
-        EXPECT_TRUE(vibrator->on(2000, nullptr /*callback*/).isOk());
-        EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(0.5f).exceptionCode());
+        EXPECT_OK(vibrator->setAmplitude(0.1f));
+        EXPECT_OK(vibrator->on(2000, nullptr /*callback*/));
+        EXPECT_OK(vibrator->setAmplitude(0.5f));
         sleep(1);
-        EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(1.0f).exceptionCode());
+        EXPECT_OK(vibrator->setAmplitude(1.0f));
         sleep(1);
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_OK(vibrator->off());
     }
 }
 
 TEST_P(VibratorAidl, AmplitudeOutsideRangeFails) {
     if (capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) {
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(-1).exceptionCode());
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(0).exceptionCode());
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(1.1).exceptionCode());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->setAmplitude(-1));
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->setAmplitude(0));
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->setAmplitude(1.1));
     }
 }
 
 TEST_P(VibratorAidl, AmplitudeReturnsUnsupportedMatchingCapabilities) {
     if ((capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) == 0) {
-        Status status = vibrator->setAmplitude(1);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->setAmplitude(1));
     }
 }
 
 TEST_P(VibratorAidl, ChangeVibrationExternalControl) {
     if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
-        EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
+        EXPECT_OK(vibrator->setExternalControl(true));
         sleep(1);
-        EXPECT_TRUE(vibrator->setExternalControl(false).isOk());
+        EXPECT_OK(vibrator->setExternalControl(false));
         sleep(1);
     }
 }
@@ -375,15 +546,15 @@
         (capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0;
 
     if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
-        EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
+        EXPECT_OK(vibrator->setExternalControl(true));
 
-        Status amplitudeStatus = vibrator->setAmplitude(0.5);
         if (supportsExternalAmplitudeControl) {
-            EXPECT_TRUE(amplitudeStatus.isOk());
+            EXPECT_OK(vibrator->setAmplitude(0.5));
         } else {
-            EXPECT_TRUE(isUnknownOrUnsupported(amplitudeStatus)) << amplitudeStatus;
+            EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->setAmplitude(0.5));
         }
-        EXPECT_TRUE(vibrator->setExternalControl(false).isOk());
+
+        EXPECT_OK(vibrator->setExternalControl(false));
     } else {
         EXPECT_FALSE(supportsExternalAmplitudeControl);
     }
@@ -391,18 +562,16 @@
 
 TEST_P(VibratorAidl, ExternalControlUnsupportedMatchingCapabilities) {
     if ((capabilities & IVibrator::CAP_EXTERNAL_CONTROL) == 0) {
-        Status status = vibrator->setExternalControl(true);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->setExternalControl(true));
     }
 }
 
 TEST_P(VibratorAidl, GetSupportedPrimitives) {
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
         std::vector<CompositePrimitive> supported;
+        EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
 
-        EXPECT_EQ(Status::EX_NONE, vibrator->getSupportedPrimitives(&supported).exceptionCode());
-
-        for (auto primitive : kCompositePrimitives) {
+        for (CompositePrimitive primitive : kCompositePrimitives) {
             bool isPrimitiveSupported =
                 std::find(supported.begin(), supported.end(), primitive) != supported.end();
             bool isPrimitiveRequired =
@@ -417,22 +586,23 @@
 TEST_P(VibratorAidl, GetPrimitiveDuration) {
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
         std::vector<CompositePrimitive> supported;
-        ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
+        EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
 
-        for (auto primitive : kCompositePrimitives) {
+        for (CompositePrimitive primitive : kCompositePrimitives) {
             bool isPrimitiveSupported =
                 std::find(supported.begin(), supported.end(), primitive) != supported.end();
             int32_t duration;
 
-            Status status = vibrator->getPrimitiveDuration(primitive, &duration);
-
             if (isPrimitiveSupported) {
-                EXPECT_EQ(Status::EX_NONE, status.exceptionCode());
+                EXPECT_OK(vibrator->getPrimitiveDuration(primitive, &duration))
+                        << "\n  For primitive: " << toString(primitive) << " " << duration;
                 if (primitive != CompositePrimitive::NOOP) {
-                    ASSERT_GT(duration, 0) << toString(primitive) << " " << duration;
+                    ASSERT_GT(duration, 0)
+                            << "\n  For primitive: " << toString(primitive) << " " << duration;
                 }
             } else {
-                EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+                EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->getPrimitiveDuration(primitive, &duration))
+                        << "\n  For primitive: " << toString(primitive);
             }
         }
     }
@@ -446,14 +616,14 @@
     std::vector<CompositePrimitive> supported;
     int32_t maxDelay, maxSize;
 
-    ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
-    EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
-    EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
+    EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
+    EXPECT_OK(vibrator->getCompositionDelayMax(&maxDelay));
+    EXPECT_OK(vibrator->getCompositionSizeMax(&maxSize));
 
     std::vector<CompositeEffect> composite;
 
     for (int i = 0; i < supported.size(); i++) {
-        auto primitive = supported[i];
+        CompositePrimitive primitive = supported[i];
         float t = static_cast<float>(i + 1) / supported.size();
         CompositeEffect effect;
 
@@ -467,8 +637,8 @@
     }
 
     if (composite.size() != 0) {
-        EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_OK(vibrator->compose(composite, nullptr));
+        EXPECT_OK(vibrator->off());
     }
 }
 
@@ -477,12 +647,12 @@
         GTEST_SKIP() << "CAP_COMPOSE_EFFECTS not supported";
     }
 
-    auto unsupported = kInvalidPrimitives;
+    std::vector<CompositePrimitive> unsupported(kInvalidPrimitives);
     std::vector<CompositePrimitive> supported;
 
-    ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
+    EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
 
-    for (auto primitive : kCompositePrimitives) {
+    for (CompositePrimitive primitive : kCompositePrimitives) {
         bool isPrimitiveSupported =
                 std::find(supported.begin(), supported.end(), primitive) != supported.end();
 
@@ -491,16 +661,15 @@
         }
     }
 
-    for (auto primitive : unsupported) {
+    for (CompositePrimitive primitive : unsupported) {
         std::vector<CompositeEffect> composite(1);
 
-        for (auto& effect : composite) {
+        for (CompositeEffect& effect : composite) {
             effect.delayMs = 0;
             effect.primitive = primitive;
             effect.scale = 1.0f;
         }
-        Status status = vibrator->compose(composite, nullptr);
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->compose(composite, nullptr));
     }
 }
 
@@ -516,18 +685,18 @@
     effect.primitive = CompositePrimitive::CLICK;
 
     effect.scale = std::nextafter(0.0f, -1.0f);
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->compose(composite, nullptr));
 
     effect.scale = 0.0f;
-    EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->compose(composite, nullptr));
+    EXPECT_OK(vibrator->off());
 
     effect.scale = 1.0f;
-    EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->compose(composite, nullptr));
+    EXPECT_OK(vibrator->off());
 
     effect.scale = std::nextafter(1.0f, 2.0f);
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->compose(composite, nullptr));
 }
 
 TEST_P(VibratorAidl, ComposeDelayBoundary) {
@@ -537,7 +706,7 @@
 
     int32_t maxDelay;
 
-    EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
+    EXPECT_OK(vibrator->getCompositionDelayMax(&maxDelay));
 
     std::vector<CompositeEffect> composite(1);
     CompositeEffect& effect = composite[0];
@@ -546,19 +715,19 @@
     effect.scale = 1.0f;
 
     effect.delayMs = 0;
-    EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->compose(composite, nullptr));
+    EXPECT_OK(vibrator->off());
 
     effect.delayMs = 1;
-    EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->compose(composite, nullptr));
+    EXPECT_OK(vibrator->off());
 
     effect.delayMs = maxDelay;
-    EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->compose(composite, nullptr));
+    EXPECT_OK(vibrator->off());
 
     effect.delayMs = maxDelay + 1;
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->compose(composite, nullptr));
 }
 
 TEST_P(VibratorAidl, ComposeSizeBoundary) {
@@ -568,7 +737,7 @@
 
     int32_t maxSize;
 
-    EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
+    EXPECT_OK(vibrator->getCompositionSizeMax(&maxSize));
 
     std::vector<CompositeEffect> composite(maxSize);
     CompositeEffect effect;
@@ -578,11 +747,11 @@
     effect.scale = 1.0f;
 
     std::fill(composite.begin(), composite.end(), effect);
-    EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->compose(composite, nullptr));
+    EXPECT_OK(vibrator->off());
 
     composite.emplace_back(effect);
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->compose(composite, nullptr).exceptionCode());
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->compose(composite, nullptr));
 }
 
 TEST_P(VibratorAidl, ComposeCallback) {
@@ -591,18 +760,17 @@
     }
 
     std::vector<CompositePrimitive> supported;
+    EXPECT_OK(vibrator->getSupportedPrimitives(&supported));
 
-    ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
-
-    for (auto primitive : supported) {
+    for (CompositePrimitive primitive : supported) {
         if (primitive == CompositePrimitive::NOOP) {
             continue;
         }
 
         std::promise<void> completionPromise;
         std::future<void> completionFuture{completionPromise.get_future()};
-        sp<CompletionCallback> callback =
-                new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+        auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+                [&completionPromise] { completionPromise.set_value(); });
         CompositeEffect effect;
         std::vector<CompositeEffect> composite;
         int32_t durationMs;
@@ -615,50 +783,50 @@
         effect.scale = 1.0f;
         composite.emplace_back(effect);
 
-        EXPECT_EQ(Status::EX_NONE,
-                  vibrator->getPrimitiveDuration(primitive, &durationMs).exceptionCode())
-                << toString(primitive);
+        EXPECT_OK(vibrator->getPrimitiveDuration(primitive, &durationMs))
+                << "\n  For primitive: " << toString(primitive);
         duration = std::chrono::milliseconds(durationMs);
 
         start = high_resolution_clock::now();
-        EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
-                << toString(primitive);
+        EXPECT_OK(vibrator->compose(composite, callback))
+                << "\n  For primitive: " << toString(primitive);
 
         EXPECT_EQ(completionFuture.wait_for(duration + VIBRATION_CALLBACK_TIMEOUT),
                   std::future_status::ready)
-                << toString(primitive);
+                << "\n  For primitive: " << toString(primitive);
         end = high_resolution_clock::now();
 
         elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
-        EXPECT_GE(elapsed.count(), duration.count()) << toString(primitive);
+        EXPECT_GE(elapsed.count(), duration.count())
+                << "\n  For primitive: " << toString(primitive);
 
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_OK(vibrator->off()) << "\n  For primitive: " << toString(primitive);
     }
 }
 
 TEST_P(VibratorAidl, AlwaysOn) {
     if (capabilities & IVibrator::CAP_ALWAYS_ON_CONTROL) {
         std::vector<Effect> supported;
-        ASSERT_TRUE(vibrator->getSupportedAlwaysOnEffects(&supported).isOk());
+        EXPECT_OK(vibrator->getSupportedAlwaysOnEffects(&supported));
 
         for (Effect effect : kEffects) {
             bool isEffectSupported =
                 std::find(supported.begin(), supported.end(), effect) != supported.end();
 
             for (EffectStrength strength : kEffectStrengths) {
-                Status status = vibrator->alwaysOnEnable(0, effect, strength);
+                ndk::ScopedAStatus status = vibrator->alwaysOnEnable(0, effect, strength);
 
                 if (isEffectSupported) {
-                    EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
-                        << toString(effect) << " " << toString(strength);
+                    EXPECT_OK(std::move(status))
+                            << "\n  For effect: " << toString(effect) << " " << toString(strength);
                 } else {
-                    EXPECT_TRUE(isUnknownOrUnsupported(status))
-                            << status << " " << toString(effect) << " " << toString(strength);
+                    EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status))
+                            << "\n  For effect: " << toString(effect) << " " << toString(strength);
                 }
             }
         }
 
-        EXPECT_EQ(Status::EX_NONE, vibrator->alwaysOnDisable(0).exceptionCode());
+        EXPECT_OK(vibrator->alwaysOnDisable(0));
     }
 }
 
@@ -668,12 +836,12 @@
 
 TEST_P(VibratorAidl, GetQFactor) {
     float qFactor;
-    Status status = vibrator->getQFactor(&qFactor);
+    ndk::ScopedAStatus status = vibrator->getQFactor(&qFactor);
     if (capabilities & IVibrator::CAP_GET_Q_FACTOR) {
+        EXPECT_OK(std::move(status));
         ASSERT_GT(qFactor, 0);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 }
 
@@ -687,9 +855,9 @@
 
 TEST_P(VibratorAidl, GetBandwidthAmplitudeMap) {
     std::vector<float> bandwidthAmplitudeMap;
-    Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
+    ndk::ScopedAStatus status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+        EXPECT_OK(std::move(status));
         ASSERT_FALSE(bandwidthAmplitudeMap.empty());
 
         int minMapSize = (getResonantFrequencyHz(vibrator, capabilities) -
@@ -702,42 +870,42 @@
             ASSERT_LE(e, 1.0);
         }
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 }
 
 TEST_P(VibratorAidl, GetPwlePrimitiveDurationMax) {
     int32_t durationMs;
-    Status status = vibrator->getPwlePrimitiveDurationMax(&durationMs);
+    ndk::ScopedAStatus status = vibrator->getPwlePrimitiveDurationMax(&durationMs);
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+        EXPECT_OK(std::move(status));
         ASSERT_NE(durationMs, 0);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 }
 
 TEST_P(VibratorAidl, GetPwleCompositionSizeMax) {
     int32_t maxSize;
-    Status status = vibrator->getPwleCompositionSizeMax(&maxSize);
+    ndk::ScopedAStatus status = vibrator->getPwleCompositionSizeMax(&maxSize);
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+        EXPECT_OK(std::move(status));
         ASSERT_NE(maxSize, 0);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 }
 
 TEST_P(VibratorAidl, GetSupportedBraking) {
     std::vector<Braking> supported;
-    Status status = vibrator->getSupportedBraking(&supported);
+    ndk::ScopedAStatus status = vibrator->getSupportedBraking(&supported);
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
         bool isDefaultNoneSupported =
             std::find(supported.begin(), supported.end(), Braking::NONE) != supported.end();
+        EXPECT_OK(std::move(status));
         ASSERT_TRUE(isDefaultNoneSupported);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
+        EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 }
 
@@ -746,7 +914,7 @@
         ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities);
 
         std::vector<Braking> supported;
-        ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
+        EXPECT_OK(vibrator->getSupportedBraking(&supported));
         bool isClabSupported =
             std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
         BrakingPwle firstBraking;
@@ -765,11 +933,11 @@
         secondBraking.braking = Braking::NONE;
         secondBraking.duration = 10;
 
-        auto pwleQueue =
-            std::vector<PrimitivePwle>{firstActive, firstBraking, secondActive, secondBraking};
+        std::vector<PrimitivePwle> pwleQueue = {firstActive, firstBraking, secondActive,
+                                                secondBraking};
 
-        EXPECT_EQ(Status::EX_NONE, vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_OK(vibrator->composePwle(pwleQueue, nullptr));
+        EXPECT_OK(vibrator->off());
     }
 }
 
@@ -780,8 +948,8 @@
 
     std::promise<void> completionPromise;
     std::future<void> completionFuture{completionPromise.get_future()};
-    sp<CompletionCallback> callback =
-        new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+    auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+            [&completionPromise] { completionPromise.set_value(); });
     int32_t segmentDurationMaxMs;
     vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
     uint32_t durationMs = segmentDurationMaxMs * 2 + 100;  // Sum of 2 active and 1 braking below
@@ -790,27 +958,25 @@
     ActivePwle active = composeValidActivePwle(vibrator, capabilities);
 
     std::vector<Braking> supported;
-    ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
+    EXPECT_OK(vibrator->getSupportedBraking(&supported));
     bool isClabSupported =
         std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
     BrakingPwle braking;
     braking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
     braking.duration = 100;
 
-    auto pwleQueue = std::vector<PrimitivePwle>{active, braking, active};
+    std::vector<PrimitivePwle> pwleQueue = {active, braking, active};
 
-    EXPECT_TRUE(vibrator->composePwle(pwleQueue, callback).isOk());
+    EXPECT_OK(vibrator->composePwle(pwleQueue, callback));
     EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
-    EXPECT_TRUE(vibrator->off().isOk());
+    EXPECT_OK(vibrator->off());
 }
 
 TEST_P(VibratorAidl, ComposePwleSegmentBoundary) {
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
         std::vector<PrimitivePwle> pwleQueue;
         // test empty queue
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueue, nullptr));
 
         ActivePwle active = composeValidActivePwle(vibrator, capabilities);
 
@@ -824,9 +990,7 @@
             pwleQueue.emplace_back(std::move(pwle));
         }
 
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueue, nullptr));
     }
 }
 
@@ -836,20 +1000,16 @@
         active.startAmplitude = getAmplitudeMax() + 1.0;  // Amplitude greater than allowed
         active.endAmplitude = getAmplitudeMax() + 1.0;    // Amplitude greater than allowed
 
-        auto pwleQueueGreater = std::vector<PrimitivePwle>{active};
+        std::vector<PrimitivePwle> pwleQueueGreater = {active};
 
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueueGreater, nullptr));
 
         active.startAmplitude = getAmplitudeMin() - 1.0;  // Amplitude less than allowed
         active.endAmplitude = getAmplitudeMin() - 1.0;    // Amplitude less than allowed
 
-        auto pwleQueueLess = std::vector<PrimitivePwle>{active};
+        std::vector<PrimitivePwle> pwleQueueLess = {active};
 
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueueLess, nullptr));
     }
 }
 
@@ -865,20 +1025,16 @@
             freqMaximumHz + freqResolutionHz;                    // Frequency greater than allowed
         active.endFrequency = freqMaximumHz + freqResolutionHz;  // Frequency greater than allowed
 
-        auto pwleQueueGreater = std::vector<PrimitivePwle>{active};
+        std::vector<PrimitivePwle> pwleQueueGreater = {active};
 
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueueGreater, nullptr));
 
         active.startFrequency = freqMinimumHz - freqResolutionHz;  // Frequency less than allowed
         active.endFrequency = freqMinimumHz - freqResolutionHz;    // Frequency less than allowed
 
-        auto pwleQueueLess = std::vector<PrimitivePwle>{active};
+        std::vector<PrimitivePwle> pwleQueueLess = {active};
 
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueueLess, nullptr));
     }
 }
 
@@ -890,32 +1046,196 @@
         vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
         active.duration = segmentDurationMaxMs + 10;  // Segment duration greater than allowed
 
-        auto pwleQueue = std::vector<PrimitivePwle>{active};
+        std::vector<PrimitivePwle> pwleQueue = {active};
 
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-                  vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
-        EXPECT_TRUE(vibrator->off().isOk());
+        EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueue, nullptr));
     }
 }
 
+TEST_P(VibratorAidl, PwleV2FrequencyToOutputAccelerationMapHasValidFrequencyRange) {
+    if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) {
+        GTEST_SKIP() << "PWLE V2 not supported, skipping test";
+        return;
+    }
+
+    std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
+    ndk::ScopedAStatus status =
+            vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap);
+    EXPECT_OK(std::move(status));
+    ASSERT_FALSE(frequencyToOutputAccelerationMap.empty());
+    auto sharpnessRange =
+            pwle_v2_utils::getPwleV2SharpnessRange(vibrator, frequencyToOutputAccelerationMap);
+    // Validate the curve provides a usable sharpness range, which is a range of frequencies
+    // that are supported by the device.
+    ASSERT_TRUE(sharpnessRange.first >= 0);
+    // Validate that the sharpness range is a valid interval, not a single point.
+    ASSERT_TRUE(sharpnessRange.first < sharpnessRange.second);
+}
+
+TEST_P(VibratorAidl, GetPwleV2PrimitiveDurationMaxMillis) {
+    if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) {
+        GTEST_SKIP() << "PWLE V2 not supported, skipping test";
+        return;
+    }
+
+    int32_t durationMs;
+    ndk::ScopedAStatus status = vibrator->getPwleV2PrimitiveDurationMaxMillis(&durationMs);
+    EXPECT_OK(std::move(status));
+    ASSERT_GT(durationMs, 0);  // Ensure greater than zero
+    ASSERT_GE(durationMs, pwle_v2_utils::COMPOSE_PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS);
+}
+
+TEST_P(VibratorAidl, GetPwleV2CompositionSizeMax) {
+    if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) {
+        GTEST_SKIP() << "PWLE V2 not supported, skipping test";
+        return;
+    }
+
+    int32_t maxSize;
+    ndk::ScopedAStatus status = vibrator->getPwleV2CompositionSizeMax(&maxSize);
+    EXPECT_OK(std::move(status));
+    ASSERT_GT(maxSize, 0);  // Ensure greater than zero
+    ASSERT_GE(maxSize, pwle_v2_utils::COMPOSE_PWLE_V2_MIN_REQUIRED_SIZE);
+}
+
+TEST_P(VibratorAidl, GetPwleV2PrimitiveDurationMinMillis) {
+    if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) {
+        GTEST_SKIP() << "PWLE V2 not supported, skipping test";
+        return;
+    }
+
+    int32_t durationMs;
+    ndk::ScopedAStatus status = vibrator->getPwleV2PrimitiveDurationMinMillis(&durationMs);
+    EXPECT_OK(std::move(status));
+    ASSERT_GT(durationMs, 0);  // Ensure greater than zero
+    ASSERT_LE(durationMs, pwle_v2_utils::COMPOSE_PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS);
+}
+
+TEST_P(VibratorAidl, ComposeValidPwleV2Effect) {
+    if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) {
+        GTEST_SKIP() << "PWLE V2 not supported, skipping test";
+        return;
+    }
+
+    EXPECT_OK(vibrator->composePwleV2(pwle_v2_utils::composeValidPwleV2Effect(vibrator), nullptr));
+    EXPECT_OK(vibrator->off());
+}
+
+TEST_P(VibratorAidl, ComposePwleV2Unsupported) {
+    if (version < PWLE_V2_MIN_VERSION) {
+        EXPECT_EQ(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2, 0)
+                << "Vibrator version " << version << " should not report PWLE V2 capability.";
+    }
+    if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2) return;
+
+    std::vector<PwleV2Primitive> pwleEffect{
+            PwleV2Primitive(/*amplitude=*/1.0f, /*frequencyHz=*/100.0f, /*timeMillis=*/50)};
+
+    EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->composePwleV2(pwleEffect, nullptr));
+}
+
+TEST_P(VibratorAidl, ComposeValidPwleV2EffectWithCallback) {
+    if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) {
+        GTEST_SKIP() << "PWLE V2 not supported, skipping test";
+        return;
+    }
+
+    std::promise<void> completionPromise;
+    std::future<void> completionFuture{completionPromise.get_future()};
+    auto callback = ndk::SharedRefBase::make<CompletionCallback>(
+            [&completionPromise] { completionPromise.set_value(); });
+
+    int32_t minDuration;
+    EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDuration));
+    auto timeout = std::chrono::milliseconds(minDuration) + VIBRATION_CALLBACK_TIMEOUT;
+    float minFrequency = pwle_v2_utils::getPwleV2FrequencyMinHz(vibrator);
+
+    EXPECT_OK(vibrator->composePwleV2(
+            {PwleV2Primitive(/*amplitude=*/0.5, minFrequency, minDuration)}, callback));
+    EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
+    EXPECT_OK(vibrator->off());
+}
+
+TEST_P(VibratorAidl, composePwleV2EffectWithTooManyPoints) {
+    if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) {
+        GTEST_SKIP() << "PWLE V2 not supported, skipping test";
+        return;
+    }
+
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(
+            pwle_v2_utils::composePwleV2EffectWithTooManyPoints(vibrator), nullptr));
+}
+
+TEST_P(VibratorAidl, composeInvalidPwleV2Effect) {
+    if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) {
+        GTEST_SKIP() << "PWLE V2 not supported, skipping test";
+        return;
+    }
+
+    // Retrieve min and max durations
+    int32_t minDurationMs, maxDurationMs;
+    EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs));
+    EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMaxMillis(&maxDurationMs));
+
+    std::vector<PwleV2Primitive> composePwle;
+
+    // Negative amplitude
+    composePwle.push_back(PwleV2Primitive(/*amplitude=*/-0.8f, /*frequency=*/100, minDurationMs));
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr))
+            << "Composing PWLE V2 effect with negative amplitude should fail";
+    composePwle.clear();
+
+    // Amplitude exceeding 1.0
+    composePwle.push_back(PwleV2Primitive(/*amplitude=*/1.2f, /*frequency=*/100, minDurationMs));
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr))
+            << "Composing PWLE V2 effect with amplitude greater than 1.0 should fail";
+    composePwle.clear();
+
+    // Duration exceeding maximum
+    composePwle.push_back(
+            PwleV2Primitive(/*amplitude=*/0.2f, /*frequency=*/100, maxDurationMs + 10));
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr))
+            << "Composing PWLE V2 effect with duration exceeding maximum should fail";
+    composePwle.clear();
+
+    // Negative duration
+    composePwle.push_back(PwleV2Primitive(/*amplitude=*/0.2f, /*frequency=*/100, /*time=*/-1));
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr))
+            << "Composing PWLE V2 effect with negative duration should fail";
+    composePwle.clear();
+
+    // Frequency below minimum
+    float minFrequency = pwle_v2_utils::getPwleV2FrequencyMinHz(vibrator);
+    composePwle.push_back(PwleV2Primitive(/*amplitude=*/0.2f, minFrequency - 1, minDurationMs));
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr))
+            << "Composing PWLE V2 effect with frequency below minimum should fail";
+    composePwle.clear();
+
+    // Frequency above maximum
+    float maxFrequency = pwle_v2_utils::getPwleV2FrequencyMaxHz(vibrator);
+    composePwle.push_back(PwleV2Primitive(/*amplitude=*/0.2f, maxFrequency + 1, minDurationMs));
+    EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr))
+            << "Composing PWLE V2 effect with frequency above maximum should fail";
+}
+
 std::vector<std::tuple<int32_t, int32_t>> GenerateVibratorMapping() {
     std::vector<std::tuple<int32_t, int32_t>> tuples;
-    auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
-    std::vector<int32_t> vibratorIds;
 
-    for (int i = 0; i < managerAidlNames.size(); i++) {
-        auto managerName = String16(managerAidlNames[i].c_str());
-        auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
+    std::vector<std::string> managerNames = findVibratorManagerNames();
+    std::vector<int32_t> vibratorIds;
+    for (int i = 0; i < managerNames.size(); i++) {
+        auto vibratorManager = IVibratorManager::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(managerNames[i].c_str())));
         if (vibratorManager->getVibratorIds(&vibratorIds).isOk()) {
-            for (auto &vibratorId : vibratorIds) {
-                tuples.push_back(std::make_tuple(i, vibratorId));
+            for (int32_t vibratorId : vibratorIds) {
+                tuples.emplace_back(i, vibratorId);
             }
         }
     }
 
-    auto vibratorAidlNames = android::getAidlHalInstanceNames(IVibrator::descriptor);
-    for (int i = 0; i < vibratorAidlNames.size(); i++) {
-        tuples.push_back(std::make_tuple(-1, i));
+    std::vector<std::string> vibratorNames = findUnmanagedVibratorNames();
+    for (int i = 0; i < vibratorNames.size(); i++) {
+        tuples.emplace_back(-1, i);
     }
 
     return tuples;
@@ -935,8 +1255,11 @@
                          PrintGeneratedTest);
 
 int main(int argc, char **argv) {
+    // Random values are used in the implementation.
+    std::srand(std::time(nullptr));
+
     ::testing::InitGoogleTest(&argc, argv);
-    ProcessState::self()->setThreadPoolMaxThreadCount(1);
-    ProcessState::self()->startThreadPool();
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
 }
diff --git a/vibrator/aidl/vts/persistable_bundle_utils.h b/vibrator/aidl/vts/persistable_bundle_utils.h
new file mode 100644
index 0000000..a765a49
--- /dev/null
+++ b/vibrator/aidl/vts/persistable_bundle_utils.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+#ifndef VIBRATOR_HAL_PERSISTABLE_BUNDLE_UTILS_H
+#define VIBRATOR_HAL_PERSISTABLE_BUNDLE_UTILS_H
+
+#include <android/persistable_bundle_aidl.h>
+
+#include <cstdlib>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace vibrator {
+namespace testing {
+
+using aidl::android::os::PersistableBundle;
+
+namespace {
+
+template <typename T>
+T nextValue() {
+    return static_cast<T>(std::rand());
+}
+
+template <>
+std::string nextValue() {
+    std::string str;
+    uint8_t entryCount = nextValue<uint8_t>();
+    for (uint8_t i = 0; i < entryCount; i++) {
+        str.push_back(nextValue<char>());
+    }
+    return str;
+}
+
+template <typename T>
+T nextValue(T limit) {
+    assert(limit > 0);
+    return static_cast<T>(std::rand()) / (static_cast<T>(RAND_MAX / limit));
+}
+
+template <typename T>
+void fillVector(std::vector<T>* values) {
+    uint8_t entryCount = nextValue<uint8_t>();
+    for (uint8_t i = 0; i < entryCount; i++) {
+        values->push_back(nextValue<T>());
+    }
+}
+
+const std::vector<std::function<void(PersistableBundle*, const std::string&)>>
+        sPersistableBundleSetters = {[](PersistableBundle* bundle, const std::string& key) -> void {
+                                         bundle->putBoolean(key, nextValue<bool>());
+                                     },
+                                     [](PersistableBundle* bundle, const std::string& key) -> void {
+                                         bundle->putInt(key, nextValue<int32_t>());
+                                     },
+                                     [](PersistableBundle* bundle, const std::string& key) -> void {
+                                         bundle->putLong(key, nextValue<int64_t>());
+                                     },
+                                     [](PersistableBundle* bundle, const std::string& key) -> void {
+                                         bundle->putDouble(key, nextValue<double>());
+                                     },
+                                     [](PersistableBundle* bundle, const std::string& key) -> void {
+                                         bundle->putString(key, nextValue<std::string>());
+                                     },
+                                     [](PersistableBundle* bundle, const std::string& key) -> void {
+                                         std::vector<bool> value;
+                                         fillVector<bool>(&value);
+                                         bundle->putBooleanVector(key, value);
+                                     },
+                                     [](PersistableBundle* bundle, const std::string& key) -> void {
+                                         std::vector<int32_t> value;
+                                         fillVector<int32_t>(&value);
+                                         bundle->putIntVector(key, value);
+                                     },
+                                     [](PersistableBundle* bundle, const std::string& key) -> void {
+                                         std::vector<int64_t> value;
+                                         fillVector<int64_t>(&value);
+                                         bundle->putLongVector(key, value);
+                                     },
+                                     [](PersistableBundle* bundle, const std::string& key) -> void {
+                                         std::vector<double> value;
+                                         fillVector<double>(&value);
+                                         bundle->putDoubleVector(key, value);
+                                     },
+                                     [](PersistableBundle* bundle, const std::string& key) -> void {
+                                         std::vector<std::string> value;
+                                         fillVector<std::string>(&value);
+                                         bundle->putStringVector(key, value);
+                                     }};
+
+}  // namespace
+
+void fillBasicData(PersistableBundle* bundle) {
+    bundle->putBoolean("test_bool", true);
+    bundle->putInt("test_int", 2147483647);
+    bundle->putLong("test_long", 2147483647L);
+    bundle->putDouble("test_double", 1.23);
+    bundle->putString("test_string", "test data");
+    bundle->putBooleanVector("test_bool_vector", {true, false, false});
+    bundle->putIntVector("test_int_vector", {1, 2, 3, 4});
+    bundle->putLongVector("test_long_vector", {100L, 200L, 300L});
+    bundle->putDoubleVector("test_double_vector", {1.1, 2.2});
+    bundle->putStringVector("test_string_vector", {"test", "val"});
+}
+
+void fillRandomData(PersistableBundle* bundle) {
+    uint8_t entryCount = nextValue<uint8_t>();
+    for (uint8_t i = 0; i < entryCount; i++) {
+        std::string key(nextValue<std::string>());
+        uint8_t setterIdx = nextValue<uint8_t>(sPersistableBundleSetters.size() - 1);
+        sPersistableBundleSetters[setterIdx](bundle, key);
+    }
+}
+
+}  // namespace testing
+}  // namespace vibrator
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // VIBRATOR_HAL_PERSISTABLE_BUNDLE_UTILS_H
diff --git a/vibrator/aidl/vts/pwle_v2_utils.h b/vibrator/aidl/vts/pwle_v2_utils.h
new file mode 100644
index 0000000..2163908
--- /dev/null
+++ b/vibrator/aidl/vts/pwle_v2_utils.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#ifndef VIBRATOR_HAL_PWLE_V2_UTILS_H
+#define VIBRATOR_HAL_PWLE_V2_UTILS_H
+
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+#include "test_utils.h"
+
+using aidl::android::hardware::vibrator::IVibrator;
+using aidl::android::hardware::vibrator::PwleV2OutputMapEntry;
+using aidl::android::hardware::vibrator::PwleV2Primitive;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace vibrator {
+namespace testing {
+namespace pwlev2 {
+
+static constexpr int32_t COMPOSE_PWLE_V2_MIN_REQUIRED_SIZE = 16;
+static constexpr int32_t COMPOSE_PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS = 1000;
+static constexpr int32_t COMPOSE_PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS = 20;
+static constexpr int32_t COMPOSE_PWLE_V2_MIN_REQUIRED_SENSITIVITY_DB_SL = 10;
+
+namespace {
+/**
+ * Returns a vector of (frequency in Hz, acceleration in dB) pairs, where the acceleration
+ * value denotes the minimum output required at the corresponding frequency to be perceptible
+ * by a human.
+ */
+static std::vector<std::pair<float, float>> getMinPerceptibleLevel() {
+    return {{0.4f, -97.81f},   {2.0f, -69.86f},   {3.0f, -62.81f},    {4.0f, -58.81f},
+            {5.0f, -56.69f},   {6.0f, -54.77f},   {7.2f, -52.85f},    {8.0f, -51.77f},
+            {8.64f, -50.84f},  {10.0f, -48.90f},  {10.37f, -48.52f},  {12.44f, -46.50f},
+            {14.93f, -44.43f}, {15.0f, -44.35f},  {17.92f, -41.96f},  {20.0f, -40.36f},
+            {21.5f, -39.60f},  {25.0f, -37.48f},  {25.8f, -36.93f},   {30.0f, -34.31f},
+            {35.0f, -33.13f},  {40.0f, -32.81f},  {50.0f, -31.94f},   {60.0f, -31.77f},
+            {70.0f, -31.59f},  {72.0f, -31.55f},  {80.0f, -31.77f},   {86.4f, -31.94f},
+            {90.0f, -31.73f},  {100.0f, -31.90f}, {103.68f, -31.77f}, {124.42f, -31.70f},
+            {149.3f, -31.38f}, {150.0f, -31.35f}, {179.16f, -31.02f}, {200.0f, -30.86f},
+            {215.0f, -30.35f}, {250.0f, -28.98f}, {258.0f, -28.68f},  {300.0f, -26.81f},
+            {400.0f, -19.81f}};
+}
+
+static float interpolateLinearly(const std::vector<float>& xAxis, const std::vector<float>& yAxis,
+                                 float x) {
+    EXPECT_TRUE(!xAxis.empty());
+    EXPECT_TRUE(xAxis.size() == yAxis.size());
+
+    if (x <= xAxis.front()) return yAxis.front();
+    if (x >= xAxis.back()) return yAxis.back();
+
+    auto it = std::upper_bound(xAxis.begin(), xAxis.end(), x);
+    int i = std::distance(xAxis.begin(), it) - 1;  // Index of the lower bound
+
+    const float& x0 = xAxis[i];
+    const float& y0 = yAxis[i];
+    const float& x1 = xAxis[i + 1];
+    const float& y1 = yAxis[i + 1];
+
+    return y0 + (x - x0) * (y1 - y0) / (x1 - x0);
+}
+
+static float minPerceptibleDbCurve(float frequency) {
+    // Initialize minPerceptibleMap only once
+    static auto minPerceptibleMap = []() -> std::function<float(float)> {
+        static std::vector<float> minPerceptibleFrequencies;
+        static std::vector<float> minPerceptibleAccelerations;
+
+        auto minPerceptibleLevel = getMinPerceptibleLevel();
+        // Sort the 'minPerceptibleLevel' data in ascending order based on the
+        // frequency values (first element of each pair).
+        std::sort(minPerceptibleLevel.begin(), minPerceptibleLevel.end(),
+                  [](const auto& a, const auto& b) { return a.first < b.first; });
+
+        for (const auto& entry : minPerceptibleLevel) {
+            minPerceptibleFrequencies.push_back(entry.first);
+            minPerceptibleAccelerations.push_back(entry.second);
+        }
+
+        return [&](float freq) {
+            return interpolateLinearly(minPerceptibleFrequencies, minPerceptibleAccelerations,
+                                       freq);
+        };
+    }();
+
+    return minPerceptibleMap(frequency);
+}
+
+static float convertSensitivityLevelToDecibel(int sl, float frequency) {
+    return sl + minPerceptibleDbCurve(frequency);
+}
+
+static float convertDecibelToAcceleration(float db) {
+    return std::pow(10.0f, db / 20.0f);
+}
+}  // namespace
+
+static float convertSensitivityLevelToAcceleration(int sl, float frequency) {
+    return pwlev2::convertDecibelToAcceleration(
+            pwlev2::convertSensitivityLevelToDecibel(sl, frequency));
+}
+
+static float getPwleV2FrequencyMinHz(const std::shared_ptr<IVibrator>& vibrator) {
+    std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
+    EXPECT_OK(
+            vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap));
+    EXPECT_TRUE(!frequencyToOutputAccelerationMap.empty());
+    // We can't use ASSERT_TRUE() above because this is a non-void function,
+    // but we need to return to assure we don't crash from a null dereference.
+    if (frequencyToOutputAccelerationMap.empty()) {
+        return std::numeric_limits<float>::quiet_NaN();
+    }
+
+    auto entry = std::min_element(
+            frequencyToOutputAccelerationMap.begin(), frequencyToOutputAccelerationMap.end(),
+            [](const auto& a, const auto& b) { return a.frequencyHz < b.frequencyHz; });
+
+    return entry->frequencyHz;
+}
+
+static float getPwleV2FrequencyMaxHz(const std::shared_ptr<IVibrator>& vibrator) {
+    std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
+    EXPECT_OK(
+            vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap));
+    EXPECT_TRUE(!frequencyToOutputAccelerationMap.empty());
+    // We can't use ASSERT_TRUE() above because this is a non-void function,
+    // but we need to return to assure we don't crash from a null dereference.
+    if (frequencyToOutputAccelerationMap.empty()) {
+        return std::numeric_limits<float>::quiet_NaN();
+    }
+
+    auto entry = std::max_element(
+            frequencyToOutputAccelerationMap.begin(), frequencyToOutputAccelerationMap.end(),
+            [](const auto& a, const auto& b) { return a.frequencyHz < b.frequencyHz; });
+
+    return entry->frequencyHz;
+}
+
+static std::vector<PwleV2Primitive> composeValidPwleV2Effect(
+        const std::shared_ptr<IVibrator>& vibrator) {
+    int32_t minDurationMs;
+    EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs));
+    int32_t maxDurationMs;
+    EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMaxMillis(&maxDurationMs));
+    float minFrequency = getPwleV2FrequencyMinHz(vibrator);
+    float maxFrequency = getPwleV2FrequencyMaxHz(vibrator);
+    int32_t maxCompositionSize;
+    EXPECT_OK(vibrator->getPwleV2CompositionSizeMax(&maxCompositionSize));
+
+    std::vector<PwleV2Primitive> pwleEffect;
+
+    pwleEffect.emplace_back(0.1f, minFrequency, minDurationMs);
+    pwleEffect.emplace_back(0.5f, maxFrequency, maxDurationMs);
+
+    float variedFrequency = (minFrequency + maxFrequency) / 2.0f;
+    for (int i = 0; i < maxCompositionSize - 2; i++) {
+        pwleEffect.emplace_back(0.7f, variedFrequency, minDurationMs);
+    }
+
+    return pwleEffect;
+}
+
+static std::vector<PwleV2Primitive> composePwleV2EffectWithTooManyPoints(
+        const std::shared_ptr<IVibrator>& vibrator) {
+    int32_t minDurationMs, maxCompositionSize;
+    EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs));
+    EXPECT_OK(vibrator->getPwleV2CompositionSizeMax(&maxCompositionSize));
+    float maxFrequency = getPwleV2FrequencyMaxHz(vibrator);
+
+    std::vector<PwleV2Primitive> pwleEffect(maxCompositionSize + 1);  // +1 to exceed the limit
+
+    std::fill(pwleEffect.begin(), pwleEffect.end(),
+              PwleV2Primitive(/*amplitude=*/0.2f, maxFrequency, minDurationMs));
+
+    return pwleEffect;
+}
+
+static std::pair<float, float> getPwleV2SharpnessRange(
+        const std::shared_ptr<IVibrator>& vibrator,
+        std::vector<PwleV2OutputMapEntry> freqToOutputAccelerationMap) {
+    std::pair<float, float> sharpnessRange = {-1, -1};
+
+    // Sort the entries by frequency in ascending order
+    std::sort(freqToOutputAccelerationMap.begin(), freqToOutputAccelerationMap.end(),
+              [](const auto& a, const auto& b) { return a.frequencyHz < b.frequencyHz; });
+
+    for (const auto& entry : freqToOutputAccelerationMap) {
+        float minAcceptableOutputAcceleration = convertSensitivityLevelToAcceleration(
+                pwlev2::COMPOSE_PWLE_V2_MIN_REQUIRED_SENSITIVITY_DB_SL, entry.frequencyHz);
+
+        if (sharpnessRange.first < 0 &&
+            minAcceptableOutputAcceleration <= entry.maxOutputAccelerationGs) {
+            sharpnessRange.first = entry.frequencyHz;  // Found the lower bound
+        } else if (sharpnessRange.first >= 0 &&
+                   minAcceptableOutputAcceleration >= entry.maxOutputAccelerationGs) {
+            sharpnessRange.second = entry.frequencyHz;  // Found the upper bound
+            return sharpnessRange;
+        }
+    }
+
+    if (sharpnessRange.first >= 0) {
+        // If only the lower bound was found, set the upper bound to the max frequency.
+        sharpnessRange.second = getPwleV2FrequencyMaxHz(vibrator);
+    }
+
+    return sharpnessRange;
+}
+}  // namespace pwlev2
+}  // namespace testing
+}  // namespace vibrator
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+#endif  // VIBRATOR_HAL_PWLE_V2_UTILS_H
diff --git a/vibrator/aidl/vts/test_utils.h b/vibrator/aidl/vts/test_utils.h
new file mode 100644
index 0000000..aaf3211
--- /dev/null
+++ b/vibrator/aidl/vts/test_utils.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+#ifndef VIBRATOR_HAL_TEST_UTILS_H
+#define VIBRATOR_HAL_TEST_UTILS_H
+
+#include <android/binder_auto_utils.h>
+#include <gtest/gtest.h>
+
+#if !defined(EXPECT_OK)
+#define EXPECT_OK(expression)                                                \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_                                            \
+    if (const ::ndk::ScopedAStatus&& _status = (expression); _status.isOk()) \
+        ;                                                                    \
+    else                                                                     \
+        ADD_FAILURE() << "Expected STATUS_OK for: " << #expression << "\n  Actual: " << _status
+#else
+#error Macro EXPECT_OK already defined unexpectedly
+#endif
+
+#if !defined(EXPECT_UNKNOWN_OR_UNSUPPORTED)
+#define EXPECT_UNKNOWN_OR_UNSUPPORTED(expression)                                                \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                                \
+    if (const ::ndk::ScopedAStatus&& _status = (expression);                                     \
+        _status.getExceptionCode() == EX_UNSUPPORTED_OPERATION ||                                \
+        _status.getStatus() == STATUS_UNKNOWN_TRANSACTION)                                       \
+        ;                                                                                        \
+    else                                                                                         \
+        ADD_FAILURE() << "Expected STATUS_UNKNOWN_TRANSACTION or EX_UNSUPPORTED_OPERATION for: " \
+                      << #expression << "\n  Actual: " << _status
+#else
+#error Macro EXPECT_UNKNOWN_OR_UNSUPPORTED already defined unexpectedly
+#endif
+
+#if !defined(EXPECT_ILLEGAL_ARGUMENT)
+#define EXPECT_ILLEGAL_ARGUMENT(expression)                                  \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_                                            \
+    if (const ::ndk::ScopedAStatus&& _status = (expression);                 \
+        _status.getExceptionCode() == EX_ILLEGAL_ARGUMENT)                   \
+        ;                                                                    \
+    else                                                                     \
+        ADD_FAILURE() << "Expected EX_ILLEGAL_ARGUMENT for: " << #expression \
+                      << "\n  Actual: " << _status
+#else
+#error Macro EXPECT_ILLEGAL_ARGUMENT already defined unexpectedly
+#endif
+
+#endif  // VIBRATOR_HAL_TEST_UTILS_H
diff --git a/vibrator/bench/Android.bp b/vibrator/bench/Android.bp
index 87bdab4..cd56516 100644
--- a/vibrator/bench/Android.bp
+++ b/vibrator/bench/Android.bp
@@ -30,12 +30,12 @@
         "benchmark.cpp",
     ],
     shared_libs: [
-        "android.hardware.vibrator-V2-cpp",
+        "android.hardware.vibrator-V3-ndk",
         "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
         "android.hardware.vibrator@1.2",
         "android.hardware.vibrator@1.3",
-        "libbinder",
+        "libbinder_ndk",
         "libhardware",
         "libhidlbase",
         "libutils",
diff --git a/vibrator/bench/benchmark.cpp b/vibrator/bench/benchmark.cpp
index deaa6f2..8fe9cf7 100644
--- a/vibrator/bench/benchmark.cpp
+++ b/vibrator/bench/benchmark.cpp
@@ -16,15 +16,14 @@
 
 #include "benchmark/benchmark.h"
 
+#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
 #include <android/hardware/vibrator/1.3/IVibrator.h>
-#include <android/hardware/vibrator/BnVibratorCallback.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
 #include <future>
 
-using ::android::enum_range;
-using ::android::sp;
 using ::android::hardware::hidl_enum_range;
 using ::android::hardware::Return;
 using ::android::hardware::details::hidl_enum_values;
@@ -33,10 +32,11 @@
 using ::benchmark::kMicrosecond;
 using ::benchmark::State;
 using ::benchmark::internal::Benchmark;
+using ::ndk::enum_range;
 
 using namespace ::std::chrono_literals;
 
-namespace Aidl = ::android::hardware::vibrator;
+namespace Aidl = ::aidl::android::hardware::vibrator;
 namespace V1_0 = ::android::hardware::vibrator::V1_0;
 namespace V1_1 = ::android::hardware::vibrator::V1_1;
 namespace V1_2 = ::android::hardware::vibrator::V1_2;
@@ -56,8 +56,8 @@
 class BaseBench : public Fixture {
   public:
     void SetUp(State& /*state*/) override {
-        android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
-        android::ProcessState::self()->startThreadPool();
+        ABinderProcess_setThreadPoolMaxThreadCount(1);
+        ABinderProcess_startThreadPool();
     }
 
     void TearDown(State& /*state*/) override {
@@ -75,7 +75,7 @@
     auto getOtherArg(const State& state, std::size_t index) const { return state.range(index + 0); }
 
   protected:
-    sp<I> mVibrator;
+    std::shared_ptr<I> mVibrator;
 };
 
 template <typename I>
@@ -83,7 +83,12 @@
   public:
     void SetUp(State& state) override {
         BaseBench<I>::SetUp(state);
-        this->mVibrator = I::getService();
+        auto service = I::getService();
+        if (service) {
+            this->mVibrator = std::shared_ptr<I>(service.release());
+        } else {
+            this->mVibrator = nullptr;
+        }
     }
 
   protected:
@@ -356,7 +361,9 @@
   public:
     void SetUp(State& state) override {
         BaseBench::SetUp(state);
-        this->mVibrator = android::waitForVintfService<Aidl::IVibrator>();
+        auto serviceName = std::string(Aidl::IVibrator::descriptor) + "/default";
+        this->mVibrator = Aidl::IVibrator::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
     }
 
     void TearDown(State& state) override {
@@ -373,14 +380,24 @@
         return (deviceCapabilities & capabilities) == capabilities;
     }
 
-    bool shouldSkipWithError(State& state, const android::binder::Status&& status) {
+    bool shouldSkipWithError(State& state, const ndk::ScopedAStatus&& status) {
         if (!status.isOk()) {
-            state.SkipWithError(status.toString8().c_str());
+            state.SkipWithError(status.getMessage());
             return true;
         }
         return false;
     }
 
+    void waitForComplete(std::future<void>& callbackFuture) {
+        // Wait until the HAL has finished processing previous vibration before starting a new one,
+        // so the HAL state is consistent on each run and metrics are less noisy. Some of the newest
+        // HAL implementations are waiting on previous vibration cleanup and might be significantly
+        // slower, so make sure we measure vibrations on a clean slate.
+        if (callbackFuture.valid()) {
+            callbackFuture.wait_for(VIBRATION_CALLBACK_TIMEOUT);
+        }
+    }
+
     static void SlowBenchConfig(Benchmark* b) { b->Iterations(VIBRATION_ITERATIONS); }
 };
 
@@ -397,18 +414,12 @@
     HalCallback() = default;
     ~HalCallback() = default;
 
-    android::binder::Status onComplete() override {
+    ndk::ScopedAStatus onComplete() override {
         mPromise.set_value();
-        return android::binder::Status::ok();
+        return ndk::ScopedAStatus::ok();
     }
 
-    void waitForComplete() {
-        // Wait until the HAL has finished processing previous vibration before starting a new one,
-        // so the HAL state is consistent on each run and metrics are less noisy. Some of the newest
-        // HAL implementations are waiting on previous vibration cleanup and might be significantly
-        // slower, so make sure we measure vibrations on a clean slate.
-        mPromise.get_future().wait_for(VIBRATION_CALLBACK_TIMEOUT);
-    }
+    std::future<void> getFuture() { return mPromise.get_future(); }
 
   private:
     std::promise<void> mPromise;
@@ -418,7 +429,11 @@
     auto ms = MAX_ON_DURATION_MS;
 
     for (auto _ : state) {
-        auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+        auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
+                          ? ndk::SharedRefBase::make<HalCallback>()
+                          : nullptr;
+        // Grab the future before callback promise is destroyed by the HAL.
+        auto cbFuture = cb ? cb->getFuture() : std::future<void>();
 
         // Test
         if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
@@ -430,9 +445,7 @@
         if (shouldSkipWithError(state, mVibrator->off())) {
             return;
         }
-        if (cb) {
-            cb->waitForComplete();
-        }
+        waitForComplete(cbFuture);
         state.ResumeTiming();
     }
 });
@@ -441,7 +454,11 @@
     auto ms = MAX_ON_DURATION_MS;
 
     for (auto _ : state) {
-        auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+        auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
+                          ? ndk::SharedRefBase::make<HalCallback>()
+                          : nullptr;
+        // Grab the future before callback promise is destroyed by the HAL.
+        auto cbFuture = cb ? cb->getFuture() : std::future<void>();
 
         // Setup
         state.PauseTiming();
@@ -457,9 +474,7 @@
 
         // Cleanup
         state.PauseTiming();
-        if (cb) {
-            cb->waitForComplete();
-        }
+        waitForComplete(cbFuture);
         state.ResumeTiming();
     }
 });
@@ -483,7 +498,9 @@
         return;
     }
 
-    auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK) ? new HalCallback() : nullptr;
+    auto cb = hasCapabilities(Aidl::IVibrator::CAP_ON_CALLBACK)
+                      ? ndk::SharedRefBase::make<HalCallback>()
+                      : nullptr;
     if (shouldSkipWithError(state, mVibrator->on(ms, cb))) {
         return;
     }
@@ -685,8 +702,11 @@
     int32_t lengthMs = 0;
 
     for (auto _ : state) {
-        auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK) ? new HalCallback()
-                                                                         : nullptr;
+        auto cb = hasCapabilities(Aidl::IVibrator::CAP_PERFORM_CALLBACK)
+                          ? ndk::SharedRefBase::make<HalCallback>()
+                          : nullptr;
+        // Grab the future before callback promise is destroyed by the HAL.
+        auto cbFuture = cb ? cb->getFuture() : std::future<void>();
 
         // Test
         if (shouldSkipWithError(state, mVibrator->perform(effect, strength, cb, &lengthMs))) {
@@ -698,9 +718,7 @@
         if (shouldSkipWithError(state, mVibrator->off())) {
             return;
         }
-        if (cb) {
-            cb->waitForComplete();
-        }
+        waitForComplete(cbFuture);
         state.ResumeTiming();
     }
 });
@@ -799,7 +817,9 @@
     effects.push_back(effect);
 
     for (auto _ : state) {
-        auto cb = new HalCallback();
+        auto cb = ndk::SharedRefBase::make<HalCallback>();
+        // Grab the future before callback promise is moved and destroyed by the HAL.
+        auto cbFuture = cb->getFuture();
 
         // Test
         if (shouldSkipWithError(state, mVibrator->compose(effects, cb))) {
@@ -811,7 +831,7 @@
         if (shouldSkipWithError(state, mVibrator->off())) {
             return;
         }
-        cb->waitForComplete();
+        waitForComplete(cbFuture);
         state.ResumeTiming();
     }
 });
diff --git a/virtualization/OWNERS b/virtualization/OWNERS
new file mode 100644
index 0000000..316145b
--- /dev/null
+++ b/virtualization/OWNERS
@@ -0,0 +1 @@
+include platform/packages/modules/Virtualization:/OWNERS
diff --git a/virtualization/capabilities_service/README.md b/virtualization/capabilities_service/README.md
new file mode 100644
index 0000000..7dc141e
--- /dev/null
+++ b/virtualization/capabilities_service/README.md
@@ -0,0 +1,9 @@
+The IVmCapabilitiesService HAL is used in a flow to grant a pVM a capability to
+issue vendor-specific SMCs. For more information see: TODO(ioffe): link the docs
+
+Here is a brief overview of the subdirectories structure:
+
+* default/ - a reference implementation of the HAL that partners can integrate
+    in their products.
+* noop/ - a no-op implementation is used in cuttlefish for mixed build testing.
+* vts/ - VTS tests for this HAL.
diff --git a/virtualization/capabilities_service/aidl/Android.bp b/virtualization/capabilities_service/aidl/Android.bp
new file mode 100644
index 0000000..b0bbbdd
--- /dev/null
+++ b/virtualization/capabilities_service/aidl/Android.bp
@@ -0,0 +1,35 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_team: "trendy_team_virtualization",
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+aidl_interface {
+    name: "android.hardware.virtualization.capabilities.capabilities_service",
+    vendor_available: true,
+    srcs: ["android/**/*.aidl"],
+    stability: "vintf",
+    backend: {
+        rust: {
+            enabled: true,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.virt",
+            ],
+        },
+    },
+    frozen: false,
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl b/virtualization/capabilities_service/aidl/aidl_api/android.hardware.virtualization.capabilities.capabilities_service/current/android/hardware/virtualization/capabilities/IVmCapabilitiesService.aidl
similarity index 88%
copy from biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
copy to virtualization/capabilities_service/aidl/aidl_api/android.hardware.virtualization.capabilities.capabilities_service/current/android/hardware/virtualization/capabilities/IVmCapabilitiesService.aidl
index 173ac17..68ff021 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
+++ b/virtualization/capabilities_service/aidl/aidl_api/android.hardware.virtualization.capabilities.capabilities_service/current/android/hardware/virtualization/capabilities/IVmCapabilitiesService.aidl
@@ -31,10 +31,8 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.biometrics.fingerprint;
-/* @hide */
+package android.hardware.virtualization.capabilities;
 @VintfStability
-parcelable EnrollmentProgressStep {
-  int durationMs;
-  android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes;
+interface IVmCapabilitiesService {
+  void grantAccessToVendorTeeServices(in ParcelFileDescriptor vmFd, in String[] vendorTeeServices);
 }
diff --git a/virtualization/capabilities_service/aidl/android/hardware/virtualization/capabilities/IVmCapabilitiesService.aidl b/virtualization/capabilities_service/aidl/android/hardware/virtualization/capabilities/IVmCapabilitiesService.aidl
new file mode 100644
index 0000000..0d09ecb
--- /dev/null
+++ b/virtualization/capabilities_service/aidl/android/hardware/virtualization/capabilities/IVmCapabilitiesService.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.virtualization.capabilities;
+
+/**
+ * Encapsulates vendor-specific capabilities that can be granted to VMs.
+ */
+@VintfStability
+interface IVmCapabilitiesService {
+    /**
+     * Grant access for the VM represented by the given vm_fd to the given vendor-owned tee
+     * services. The names in |vendorTeeServices| must match the ones defined in the
+     * tee_service_contexts files.
+     * TODO(ioffe): link to the integration doc for custom smc filtering feature once
+     * it's ready.
+     */
+    void grantAccessToVendorTeeServices(
+            in ParcelFileDescriptor vmFd, in String[] vendorTeeServices);
+}
diff --git a/virtualization/capabilities_service/noop/Android.bp b/virtualization/capabilities_service/noop/Android.bp
new file mode 100644
index 0000000..37dc1a7
--- /dev/null
+++ b/virtualization/capabilities_service/noop/Android.bp
@@ -0,0 +1,34 @@
+package {
+    default_team: "trendy_team_virtualization",
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_binary {
+    name: "android.hardware.virtualization.capabilities.capabilities_service-noop",
+    relative_install_path: "hw",
+    vendor: true,
+    installable: true,
+    prefer_rlib: true,
+    rustlibs: [
+        "android.hardware.virtualization.capabilities.capabilities_service-V1-rust",
+        "libanyhow",
+        "libandroid_logger",
+        "libbinder_rs",
+        "liblog_rust",
+    ],
+    srcs: [
+        "src/main.rs",
+    ],
+    init_rc: [
+        "android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.rc",
+    ],
+    vintf_fragment_modules: [
+        "android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.xml",
+    ],
+}
+
+vintf_fragment {
+    name: "android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.xml",
+    src: "android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.xml",
+    vendor: true,
+}
diff --git a/virtualization/capabilities_service/noop/android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.rc b/virtualization/capabilities_service/noop/android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.rc
new file mode 100644
index 0000000..58c554a
--- /dev/null
+++ b/virtualization/capabilities_service/noop/android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.rc
@@ -0,0 +1,6 @@
+service vendor.vm_capabilities_service /vendor/bin/hw/android.hardware.virtualization.capabilities.capabilities_service-noop
+  interface aidl android.hardware.virtualization.capabilities.IVmCapabilitiesService/noop
+  class hal
+  disabled
+  user nobody
+  group nobody
diff --git a/virtualization/capabilities_service/noop/android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.xml b/virtualization/capabilities_service/noop/android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.xml
new file mode 100644
index 0000000..8ecb9e5
--- /dev/null
+++ b/virtualization/capabilities_service/noop/android.hardware.virtualization.capabilities.no_op_vm_capabilities_service.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.virtualization.capabilities</name>
+        <version>1</version>
+        <interface>
+            <name>IVmCapabilitiesService</name>
+            <instance>noop</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/virtualization/capabilities_service/noop/src/aidl.rs b/virtualization/capabilities_service/noop/src/aidl.rs
new file mode 100644
index 0000000..8d85e49
--- /dev/null
+++ b/virtualization/capabilities_service/noop/src/aidl.rs
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2025 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.
+ */
+
+//! No-op implementation of the IVmCapabilitiesService AIDL interface.
+
+use android_hardware_virtualization_capabilities_capabilities_service::aidl::android::hardware::virtualization::capabilities::IVmCapabilitiesService::IVmCapabilitiesService;
+use binder::{Interface, ParcelFileDescriptor};
+use log::info;
+
+/// No-op implementation of IVmCapabilitiesService
+pub struct NoOpVmCapabilitiesService {}
+
+impl NoOpVmCapabilitiesService {
+    pub fn init() -> NoOpVmCapabilitiesService {
+        let service = NoOpVmCapabilitiesService {};
+        service
+    }
+}
+
+impl Interface for NoOpVmCapabilitiesService {}
+
+impl IVmCapabilitiesService for NoOpVmCapabilitiesService {
+
+    fn grantAccessToVendorTeeServices(&self,
+        vm_fd: &ParcelFileDescriptor, tee_services: &[String]) -> binder::Result<()> {
+        info!("received {vm_fd:?} {tee_services:?}");
+        Ok(())
+    }
+}
diff --git a/virtualization/capabilities_service/noop/src/main.rs b/virtualization/capabilities_service/noop/src/main.rs
new file mode 100644
index 0000000..9440996
--- /dev/null
+++ b/virtualization/capabilities_service/noop/src/main.rs
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2025 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.
+ */
+
+//! No-op implementation of the IVmCapabilitiesService.
+
+mod aidl;
+
+use crate::aidl::NoOpVmCapabilitiesService;
+use anyhow::{bail, Context, Result};
+use log::{error, info, LevelFilter};
+use binder::{register_lazy_service, BinderFeatures, ProcessState};
+use android_hardware_virtualization_capabilities_capabilities_service::aidl::android::hardware::virtualization::capabilities::IVmCapabilitiesService::BnVmCapabilitiesService;
+
+const SERVICE_NAME: &str = "android.hardware.virtualization.capabilities.IVmCapabilitiesService/noop";
+
+fn try_main() -> Result<()> {
+    // Initialize Android logging.
+    android_logger::init_once(
+        android_logger::Config::default()
+            .with_tag("NoOpIVmCapabilitiesService")
+            .with_max_level(LevelFilter::Info)
+            .with_log_buffer(android_logger::LogId::System),
+    );
+
+    ProcessState::start_thread_pool();
+    let service_impl = NoOpVmCapabilitiesService::init();
+    let service = BnVmCapabilitiesService::new_binder(service_impl, BinderFeatures::default());
+    register_lazy_service(SERVICE_NAME, service.as_binder())
+        .with_context(|| format!("failed to register {SERVICE_NAME}"))?;
+    info!("Registered Binder service, joining threadpool.");
+    ProcessState::join_thread_pool();
+    bail!("thread pool unexpectedly ended");
+}
+
+fn main() {
+    if let Err(e) = try_main() {
+        error!("failed with {e:?}");
+        std::process::exit(1);
+    }
+}
diff --git a/virtualization/capabilities_service/vts/Android.bp b/virtualization/capabilities_service/vts/Android.bp
new file mode 100644
index 0000000..1aa21c9
--- /dev/null
+++ b/virtualization/capabilities_service/vts/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    default_team: "trendy_team_virtualization",
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_test {
+    name: "VtsVmCapabilitiesServiceTest",
+    srcs: ["tests.rs"],
+    defaults: [
+        "rdroidtest.defaults",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+    test_config: "AndroidTest.xml",
+    rustlibs: [
+        "android.hardware.virtualization.capabilities.capabilities_service-V1-rust",
+        "libbinder_rs",
+    ],
+    require_root: true,
+}
diff --git a/virtualization/capabilities_service/vts/AndroidTest.xml b/virtualization/capabilities_service/vts/AndroidTest.xml
new file mode 100644
index 0000000..2c3dadb
--- /dev/null
+++ b/virtualization/capabilities_service/vts/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2025 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.
+-->
+<configuration description="Config for VmCapabilitiesService VTS tests.">
+  <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+  <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+    <option name="push-file" key="VtsVmCapabilitiesServiceTest"
+      value="/data/local/tmp/VtsVmCapabilitiesServiceTest" />
+  </target_preparer>
+
+  <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
+    <option name="test-device-path" value="/data/local/tmp" />
+    <option name="module-name" value="VtsVmCapabilitiesServiceTest" />
+  </test>
+</configuration>
diff --git a/virtualization/capabilities_service/vts/tests.rs b/virtualization/capabilities_service/vts/tests.rs
new file mode 100644
index 0000000..9f0b7fd
--- /dev/null
+++ b/virtualization/capabilities_service/vts/tests.rs
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2025 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.
+ */
+
+use android_hardware_virtualization_capabilities_capabilities_service::aidl::android::hardware::virtualization::capabilities::IVmCapabilitiesService::IVmCapabilitiesService;
+use rdroidtest::rdroidtest;
+use std::fs::File;
+
+const VM_CAPABILITIES_SERVICE: &str =
+    "android.hardware.virtualization.capabilities.IVmCapabilitiesService";
+
+/// Returns all available instances of VmCapabilitiesService.
+/// Note: it actually returns a pair of (<instance_name>, <instance_name)). This is a requirement
+/// of the rdroidtest framework for parameterized tests. See
+/// platform_testing/libraries/rdroidtest/README.md for more information.
+fn get_instances() -> Vec<(String, String)> {
+    binder::get_declared_instances(VM_CAPABILITIES_SERVICE)
+        .unwrap_or_default()
+        .into_iter()
+        .map(|v| (v.clone(), v))
+        .collect()
+}
+
+fn connect(instance: &str) -> binder::Strong<dyn IVmCapabilitiesService> {
+    let name = format!("{VM_CAPABILITIES_SERVICE}/{instance}");
+    binder::wait_for_interface(&name).unwrap()
+}
+
+/// A very basic test that simply connects to the service and send bogus data.
+#[rdroidtest(get_instances())]
+fn connect_to_service(instance: String) {
+    let service = connect(&instance);
+    let dev_null = File::open("/dev/null").expect("failed to open /dev/null");
+    let fd = binder::ParcelFileDescriptor::new(dev_null);
+    // In this test we don't care what service returns.
+    let _ = service.grantAccessToVendorTeeServices(&fd, &[]);
+}
+
+rdroidtest::test_main!();
diff --git a/vr/1.0/vts/functional/Android.bp b/vr/1.0/vts/functional/Android.bp
index 8e23f4f..267a1cc 100644
--- a/vr/1.0/vts/functional/Android.bp
+++ b/vr/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index ebfa164..e3c269d 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index a8f3470..123c8a3 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/wifi/1.2/vts/functional/Android.bp b/wifi/1.2/vts/functional/Android.bp
index f43892b..2b85d0c 100644
--- a/wifi/1.2/vts/functional/Android.bp
+++ b/wifi/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/wifi/1.3/vts/functional/Android.bp b/wifi/1.3/vts/functional/Android.bp
index 16f84ef..a171ba8 100644
--- a/wifi/1.3/vts/functional/Android.bp
+++ b/wifi/1.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/wifi/1.4/vts/functional/Android.bp b/wifi/1.4/vts/functional/Android.bp
index cac8c0b..a1be952 100644
--- a/wifi/1.4/vts/functional/Android.bp
+++ b/wifi/1.4/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/wifi/1.5/vts/functional/Android.bp b/wifi/1.5/vts/functional/Android.bp
index d906d06..9dba217 100644
--- a/wifi/1.5/vts/functional/Android.bp
+++ b/wifi/1.5/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/wifi/1.6/vts/functional/Android.bp b/wifi/1.6/vts/functional/Android.bp
index 92e6d13..188c67c 100644
--- a/wifi/1.6/vts/functional/Android.bp
+++ b/wifi/1.6/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "hardware_interfaces_license"
diff --git a/wifi/aidl/default/Android.bp b/wifi/aidl/default/Android.bp
index 362ef1b..3fcb77f 100644
--- a/wifi/aidl/default/Android.bp
+++ b/wifi/aidl/default/Android.bp
@@ -112,9 +112,14 @@
     export_include_dirs: ["."],
 }
 
+vintf_fragment {
+    name: "android.hardware.wifi-service.xml",
+    src: "android.hardware.wifi-service.xml",
+    vendor: true,
+}
+
 cc_binary {
     name: "android.hardware.wifi-service",
-    vintf_fragments: ["android.hardware.wifi-service.xml"],
     relative_install_path: "hw",
     proprietary: true,
     cppflags: [
@@ -137,11 +142,11 @@
     ],
     static_libs: ["android.hardware.wifi-service-lib"],
     init_rc: ["android.hardware.wifi-service.rc"],
+    vintf_fragment_modules: ["android.hardware.wifi-service.xml"],
 }
 
 cc_binary {
     name: "android.hardware.wifi-service-lazy",
-    vintf_fragments: ["android.hardware.wifi-service.xml"],
     overrides: ["android.hardware.wifi-service"],
     cflags: ["-DLAZY_SERVICE"],
     relative_install_path: "hw",
@@ -166,6 +171,7 @@
     ],
     static_libs: ["android.hardware.wifi-service-lib"],
     init_rc: ["android.hardware.wifi-service-lazy.rc"],
+    vintf_fragment_modules: ["android.hardware.wifi-service.xml"],
 }
 
 cc_test {
@@ -218,3 +224,8 @@
     name: "default-android.hardware.wifi-service.xml",
     srcs: ["android.hardware.wifi-service.xml"],
 }
+
+filegroup {
+    name: "default-android.hardware.wifi-service-lazy.rc",
+    srcs: ["android.hardware.wifi-service-lazy.rc"],
+}
diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp
index d82450e..d99edaa 100644
--- a/wifi/aidl/default/aidl_struct_util.cpp
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -3394,6 +3394,7 @@
     *legacy_request = {};
 
     legacy_request->service_instance_id = aidl_request.bootstrappingInstanceId;
+    legacy_request->bootstrapping_instance_id = aidl_request.bootstrappingInstanceId;
     legacy_request->rsp_code = aidl_request.acceptRequest ? NAN_BOOTSTRAPPING_REQUEST_ACCEPT
                                                           : NAN_BOOTSTRAPPING_REQUEST_REJECT;
     legacy_request->publish_subscribe_id = static_cast<uint8_t>(aidl_request.discoverySessionId);
diff --git a/wifi/aidl/default/wifi_chip.cpp b/wifi/aidl/default/wifi_chip.cpp
index 9b9c565..fccfc15 100644
--- a/wifi/aidl/default/wifi_chip.cpp
+++ b/wifi/aidl/default/wifi_chip.cpp
@@ -62,7 +62,9 @@
 std::vector<std::string> getNames(std::vector<std::shared_ptr<Iface>>& ifaces) {
     std::vector<std::string> names;
     for (const auto& iface : ifaces) {
-        names.emplace_back(iface->getName());
+        if (iface) {
+            names.emplace_back(iface->getName());
+        }
     }
     return names;
 }
@@ -971,6 +973,10 @@
     }
     std::shared_ptr<WifiNanIface> iface =
             WifiNanIface::create(ifname, is_dedicated_iface, legacy_hal_, iface_util_);
+    if (!iface) {
+        LOG(ERROR) << "Unable to create NAN iface";
+        return {nullptr, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+    }
     nan_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
         if (!callback->onIfaceAdded(IfaceType::NAN_IFACE, ifname).isOk()) {
diff --git a/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp b/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
index 21d50ac..c68d8fd 100644
--- a/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
+++ b/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
@@ -177,8 +177,7 @@
     return iface;
 }
 
-std::shared_ptr<IWifiApIface> getWifiApIface(const char* instance_name) {
-    std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(instance_name);
+std::shared_ptr<IWifiApIface> getWifiApIface(std::shared_ptr<IWifiChip> wifi_chip) {
     if (!wifi_chip.get()) {
         return nullptr;
     }
@@ -193,6 +192,11 @@
     return iface;
 }
 
+std::shared_ptr<IWifiApIface> getWifiApIface(const char* instance_name) {
+    std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(instance_name);
+    return getWifiApIface(wifi_chip);
+}
+
 std::shared_ptr<IWifiApIface> getBridgedWifiApIface(std::shared_ptr<IWifiChip> wifi_chip) {
     if (!wifi_chip.get()) {
         return nullptr;
diff --git a/wifi/aidl/vts/functional/wifi_aidl_test_utils.h b/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
index 1369dd4..9b47a9f 100644
--- a/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
+++ b/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
@@ -40,6 +40,7 @@
 std::shared_ptr<IWifiStaIface> getWifiStaIface(const char* instance_name);
 std::shared_ptr<IWifiNanIface> getWifiNanIface(const char* instance_name);
 std::shared_ptr<IWifiApIface> getWifiApIface(const char* instance_name);
+std::shared_ptr<IWifiApIface> getWifiApIface(std::shared_ptr<IWifiChip> wifi_chip);
 std::shared_ptr<IWifiApIface> getBridgedWifiApIface(const char* instance_name);
 std::shared_ptr<IWifiApIface> getBridgedWifiApIface(std::shared_ptr<IWifiChip> wifi_chip);
 // Configure the chip in a mode to support the creation of the provided iface type.
diff --git a/wifi/aidl/vts/functional/wifi_ap_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_ap_iface_aidl_test.cpp
index d39cfb4..a58fd5b 100644
--- a/wifi/aidl/vts/functional/wifi_ap_iface_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_ap_iface_aidl_test.cpp
@@ -37,12 +37,21 @@
                 "/system/bin/cmd wifi get-softap-supported-features",
                 "wifi_softap_bridged_ap_supported");
         stopWifiService(getInstanceName());
+
+        wifi_chip_ = getWifiChip(getInstanceName());
+        ASSERT_NE(nullptr, wifi_chip_.get());
+
+        bool isApSupported = doesChipSupportConcurrencyType(wifi_chip_, IfaceConcurrencyType::AP);
+        if (!isApSupported) {
+            GTEST_SKIP() << "AP interfaces are not supported";
+        }
     }
 
     void TearDown() override { stopWifiService(getInstanceName()); }
 
   protected:
     bool isBridgedSupport_ = false;
+    std::shared_ptr<IWifiChip> wifi_chip_;
     const char* getInstanceName() { return GetParam().c_str(); }
 };
 
@@ -50,7 +59,7 @@
  * SetMacAddress
  */
 TEST_P(WifiApIfaceAidlTest, SetMacAddress) {
-    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(wifi_chip_);
     ASSERT_NE(nullptr, wifi_ap_iface.get());
     std::array<uint8_t, 6> mac = {0x12, 0x22, 0x33, 0x52, 0x10, 0x44};
     EXPECT_TRUE(wifi_ap_iface->setMacAddress(mac).isOk());
@@ -60,7 +69,7 @@
  * SetCountryCode
  */
 TEST_P(WifiApIfaceAidlTest, SetCountryCode) {
-    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(wifi_chip_);
     ASSERT_NE(nullptr, wifi_ap_iface.get());
 
     const std::array<uint8_t, 2> country_code = {0x55, 0x53};
@@ -71,7 +80,7 @@
  * GetFactoryMacAddress
  */
 TEST_P(WifiApIfaceAidlTest, GetFactoryMacAddress) {
-    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(wifi_chip_);
     ASSERT_NE(nullptr, wifi_ap_iface.get());
 
     std::array<uint8_t, 6> mac;
@@ -84,7 +93,7 @@
  * GetBridgedInstances - non-bridged mode
  */
 TEST_P(WifiApIfaceAidlTest, GetBridgedInstances) {
-    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(wifi_chip_);
     ASSERT_NE(nullptr, wifi_ap_iface.get());
 
     std::vector<std::string> instances;
@@ -99,7 +108,7 @@
     if (!isBridgedSupport_) {
         GTEST_SKIP() << "Missing Bridged AP support";
     }
-    std::shared_ptr<IWifiApIface> wifi_ap_iface = getBridgedWifiApIface(getInstanceName());
+    std::shared_ptr<IWifiApIface> wifi_ap_iface = getBridgedWifiApIface(wifi_chip_);
     ASSERT_NE(nullptr, wifi_ap_iface.get());
 
     std::vector<std::string> instances;
@@ -111,7 +120,7 @@
  * ResetToFactoryMacAddress - non-bridged mode
  */
 TEST_P(WifiApIfaceAidlTest, ResetToFactoryMacAddress) {
-    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(wifi_chip_);
     ASSERT_NE(nullptr, wifi_ap_iface.get());
     EXPECT_TRUE(wifi_ap_iface->resetToFactoryMacAddress().isOk());
 }
@@ -123,7 +132,7 @@
     if (!isBridgedSupport_) {
         GTEST_SKIP() << "Missing Bridged AP support";
     }
-    std::shared_ptr<IWifiApIface> wifi_ap_iface = getBridgedWifiApIface(getInstanceName());
+    std::shared_ptr<IWifiApIface> wifi_ap_iface = getBridgedWifiApIface(wifi_chip_);
     ASSERT_NE(nullptr, wifi_ap_iface.get());
     EXPECT_TRUE(wifi_ap_iface->resetToFactoryMacAddress().isOk());
 }
diff --git a/wifi/hostapd/aidl/Android.bp b/wifi/hostapd/aidl/Android.bp
index 2e4d4d1..88f4ef2 100644
--- a/wifi/hostapd/aidl/Android.bp
+++ b/wifi/hostapd/aidl/Android.bp
@@ -65,5 +65,5 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 }
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/BandMask.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/BandMask.aidl
index b1e7f66..fa9f198 100644
--- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/BandMask.aidl
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/BandMask.aidl
@@ -34,8 +34,8 @@
 package android.hardware.wifi.hostapd;
 @Backing(type="int") @VintfStability
 enum BandMask {
-  BAND_2_GHZ = 1,
-  BAND_5_GHZ = 2,
-  BAND_6_GHZ = 4,
-  BAND_60_GHZ = 8,
+  BAND_2_GHZ = (1 << 0) /* 1 */,
+  BAND_5_GHZ = (1 << 1) /* 2 */,
+  BAND_6_GHZ = (1 << 2) /* 4 */,
+  BAND_60_GHZ = (1 << 3) /* 8 */,
 }
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/EncryptionType.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/EncryptionType.aidl
index a7b20fa..840b875 100644
--- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/EncryptionType.aidl
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/EncryptionType.aidl
@@ -34,11 +34,11 @@
 package android.hardware.wifi.hostapd;
 @Backing(type="int") @VintfStability
 enum EncryptionType {
-  NONE = 0,
-  WPA = 1,
-  WPA2 = 2,
-  WPA3_SAE_TRANSITION = 3,
-  WPA3_SAE = 4,
-  WPA3_OWE_TRANSITION = 5,
-  WPA3_OWE = 6,
+  NONE,
+  WPA,
+  WPA2,
+  WPA3_SAE_TRANSITION,
+  WPA3_SAE,
+  WPA3_OWE_TRANSITION,
+  WPA3_OWE,
 }
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Generation.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Generation.aidl
index 5bb0d32..a0c1886 100644
--- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Generation.aidl
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Generation.aidl
@@ -34,7 +34,7 @@
 package android.hardware.wifi.hostapd;
 @Backing(type="int") @VintfStability
 enum Generation {
-  WIFI_STANDARD_UNKNOWN = -1,
+  WIFI_STANDARD_UNKNOWN = (-1) /* -1 */,
   WIFI_STANDARD_LEGACY = 0,
   WIFI_STANDARD_11N = 1,
   WIFI_STANDARD_11AC = 2,
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/HostapdStatusCode.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/HostapdStatusCode.aidl
index 548e497..7edff15 100644
--- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/HostapdStatusCode.aidl
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/HostapdStatusCode.aidl
@@ -34,10 +34,10 @@
 package android.hardware.wifi.hostapd;
 @Backing(type="int") @VintfStability
 enum HostapdStatusCode {
-  SUCCESS = 0,
-  FAILURE_UNKNOWN = 1,
-  FAILURE_ARGS_INVALID = 2,
-  FAILURE_IFACE_UNKNOWN = 3,
-  FAILURE_IFACE_EXISTS = 4,
-  FAILURE_CLIENT_UNKNOWN = 5,
+  SUCCESS,
+  FAILURE_UNKNOWN,
+  FAILURE_ARGS_INVALID,
+  FAILURE_IFACE_UNKNOWN,
+  FAILURE_IFACE_EXISTS,
+  FAILURE_CLIENT_UNKNOWN,
 }
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl
index 64367bb..8da3441 100644
--- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl
@@ -38,4 +38,6 @@
   android.hardware.wifi.hostapd.HwModeParams hwModeParams;
   android.hardware.wifi.hostapd.ChannelParams[] channelParams;
   @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
+  @nullable String[] instanceIdentities;
+  boolean isMlo;
 }
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl
index 3f8ee39..bb646e3 100644
--- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl
@@ -41,4 +41,12 @@
      * Optional vendor-specific configuration parameters.
      */
     @nullable OuiKeyedData[] vendorData;
+    /**
+     * The list of the instance identities.
+     */
+    @nullable String[] instanceIdentities;
+    /**
+     * Whether the current iface is MLO.
+     */
+    boolean isMlo;
 }
diff --git a/wifi/hostapd/aidl/vts/functional/Android.bp b/wifi/hostapd/aidl/vts/functional/Android.bp
index f614679..bf1b0d0 100644
--- a/wifi/hostapd/aidl/vts/functional/Android.bp
+++ b/wifi/hostapd/aidl/vts/functional/Android.bp
@@ -21,7 +21,7 @@
         "libvndksupport",
     ],
     static_libs: [
-        "android.hardware.wifi.hostapd-V2-ndk",
+        "android.hardware.wifi.hostapd-V3-ndk",
         "VtsHalWifiV1_0TargetTestUtil",
         "VtsHalWifiV1_5TargetTestUtil",
         "VtsHalWifiV1_6TargetTestUtil",
diff --git a/wifi/legacy_headers/include/hardware_legacy/wifi_nan.h b/wifi/legacy_headers/include/hardware_legacy/wifi_nan.h
index 55034d1..4e490d9 100644
--- a/wifi/legacy_headers/include/hardware_legacy/wifi_nan.h
+++ b/wifi/legacy_headers/include/hardware_legacy/wifi_nan.h
@@ -2972,11 +2972,17 @@
     u16 publish_subscribe_id;
 
     /*
-       This Id is the Peer Instance that is passed as
-       part of earlier MatchInd/FollowupInd message.
+      Same as the bootstrapping_instance_id
     */
     u32 service_instance_id;
 
+    /*
+      Unique Instance Id corresponding to a service/session.
+      This is similar to the publish_id generated on the
+      publisher side
+    */
+    u32 bootstrapping_instance_id;
+
     /* Discovery MAC addr of the peer/initiator */
     u8 peer_disc_mac_addr[NAN_MAC_ADDR_LEN];
 
diff --git a/wifi/netlinkinterceptor/aidl/Android.bp b/wifi/netlinkinterceptor/aidl/Android.bp
index 8c04e31..bc02125 100644
--- a/wifi/netlinkinterceptor/aidl/Android.bp
+++ b/wifi/netlinkinterceptor/aidl/Android.bp
@@ -29,6 +29,7 @@
     vendor_available: true,
     srcs: ["android/hardware/net/nlinterceptor/*.aidl"],
     stability: "vintf",
+    frozen: true,
     backend: {
         java: {
             enabled: false,
diff --git a/wifi/netlinkinterceptor/aidl/default/Android.bp b/wifi/netlinkinterceptor/aidl/default/Android.bp
index 6bdd9fc..52f15e4 100644
--- a/wifi/netlinkinterceptor/aidl/default/Android.bp
+++ b/wifi/netlinkinterceptor/aidl/default/Android.bp
@@ -76,3 +76,13 @@
     sub_dir: "vintf",
     installable: false,
 }
+
+filegroup {
+    name: "android.hardware.net.nlinterceptor-service.rc",
+    srcs: ["nlinterceptor.rc"],
+}
+
+filegroup {
+    name: "android.hardware.net.nlinterceptor.xml",
+    srcs: ["nlinterceptor.xml"],
+}
diff --git a/wifi/supplicant/aidl/Android.bp b/wifi/supplicant/aidl/Android.bp
index b7242ed..8d16cb7 100644
--- a/wifi/supplicant/aidl/Android.bp
+++ b/wifi/supplicant/aidl/Android.bp
@@ -71,5 +71,5 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 }
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
index 330f2aa..6bae4cf 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
@@ -41,4 +41,5 @@
   TRUST_ON_FIRST_USE = (1 << 4) /* 16 */,
   SET_TLS_MINIMUM_VERSION = (1 << 5) /* 32 */,
   TLS_V1_3 = (1 << 6) /* 64 */,
+  RSN_OVERRIDING = (1 << 7) /* 128 */,
 }
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
index a9434c4..b6e57c6 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
@@ -50,4 +50,8 @@
      * TLS V1.3
      */
     TLS_V1_3 = 1 << 6,
+    /**
+     * RSN Overriding
+     */
+    RSN_OVERRIDING = 1 << 7,
 }
diff --git a/wifi/supplicant/aidl/vts/functional/Android.bp b/wifi/supplicant/aidl/vts/functional/Android.bp
index 4166850..4ffec3f 100644
--- a/wifi/supplicant/aidl/vts/functional/Android.bp
+++ b/wifi/supplicant/aidl/vts/functional/Android.bp
@@ -46,7 +46,7 @@
         "android.hardware.wifi.common-V1-ndk",
         "android.hardware.wifi.supplicant@1.0",
         "android.hardware.wifi.supplicant@1.1",
-        "android.hardware.wifi.supplicant-V3-ndk",
+        "android.hardware.wifi.supplicant-V4-ndk",
         "libwifi-system",
         "libwifi-system-iface",
         "VtsHalWifiV1_0TargetTestUtil",
@@ -84,7 +84,7 @@
         "android.hardware.wifi.common-V1-ndk",
         "android.hardware.wifi.supplicant@1.0",
         "android.hardware.wifi.supplicant@1.1",
-        "android.hardware.wifi.supplicant-V3-ndk",
+        "android.hardware.wifi.supplicant-V4-ndk",
         "libwifi-system",
         "libwifi-system-iface",
         "VtsHalWifiV1_0TargetTestUtil",
@@ -122,7 +122,7 @@
         "android.hardware.wifi.common-V1-ndk",
         "android.hardware.wifi.supplicant@1.0",
         "android.hardware.wifi.supplicant@1.1",
-        "android.hardware.wifi.supplicant-V3-ndk",
+        "android.hardware.wifi.supplicant-V4-ndk",
         "libwifi-system",
         "libwifi-system-iface",
         "VtsHalWifiV1_0TargetTestUtil",