Merge "wifi: Send channel change event to framework"
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 691cf34..6b948dd 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -41,6 +41,7 @@
         "android/hardware/audio/common/SinkMetadata.aidl",
         "android/hardware/audio/common/SourceMetadata.aidl",
     ],
+    frozen: true,
     imports: [
         "android.media.audio.common.types-V2",
     ],
@@ -177,6 +178,7 @@
         "android/hardware/audio/effect/Descriptor.aidl",
         "android/hardware/audio/effect/Downmix.aidl",
         "android/hardware/audio/effect/DynamicsProcessing.aidl",
+        "android/hardware/audio/effect/EnvironmentalReverb.aidl",
         "android/hardware/audio/effect/Equalizer.aidl",
         "android/hardware/audio/effect/Flags.aidl",
         "android/hardware/audio/effect/HapticGenerator.aidl",
@@ -184,8 +186,8 @@
         "android/hardware/audio/effect/IFactory.aidl",
         "android/hardware/audio/effect/LoudnessEnhancer.aidl",
         "android/hardware/audio/effect/Parameter.aidl",
+        "android/hardware/audio/effect/PresetReverb.aidl",
         "android/hardware/audio/effect/Processing.aidl",
-        "android/hardware/audio/effect/Reverb.aidl",
         "android/hardware/audio/effect/State.aidl",
         "android/hardware/audio/effect/VendorExtension.aidl",
         "android/hardware/audio/effect/Virtualizer.aidl",
diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING
index 6473d23..484320f 100644
--- a/audio/aidl/TEST_MAPPING
+++ b/audio/aidl/TEST_MAPPING
@@ -2,6 +2,18 @@
   "presubmit": [
     {
       "name": "VtsHalAudioCoreTargetTest"
+    },
+    {
+      "name": "VtsHalAudioEffectFactoryTargetTest"
+    },
+    {
+      "name": "VtsHalAudioEffectTargetTest"
+    },
+    {
+      "name": "VtsHalEqualizerTargetTest"
+    },
+    {
+      "name": "VtsHalLoudnessEnhancerTargetTest"
     }
   ]
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl
index 163b7a0..9ce45bb 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl
@@ -35,4 +35,5 @@
 @VintfStability
 interface IConfig {
   android.hardware.audio.core.SurroundSoundConfig getSurroundSoundConfig();
+  android.media.audio.common.AudioHalEngineConfig getEngineConfig();
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/BassBoost.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/BassBoost.aidl
index 979ebb8..09ad015 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/BassBoost.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/BassBoost.aidl
@@ -36,6 +36,8 @@
 union BassBoost {
   android.hardware.audio.effect.VendorExtension vendor;
   int strengthPm;
+  const int MIN_PER_MILLE_STRENGTH = 0;
+  const int MAX_PER_MILLE_STRENGTH = 1000;
   @VintfStability
   union Id {
     int vendorExtensionTag;
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl
index 06f2bfe..60c88d3 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl
@@ -38,10 +38,11 @@
   android.hardware.audio.effect.BassBoost.Capability bassBoost;
   android.hardware.audio.effect.Downmix.Capability downmix;
   android.hardware.audio.effect.DynamicsProcessing.Capability dynamicsProcessing;
+  android.hardware.audio.effect.EnvironmentalReverb.Capability environmentalReverb;
   android.hardware.audio.effect.Equalizer.Capability equalizer;
   android.hardware.audio.effect.HapticGenerator.Capability hapticGenerator;
   android.hardware.audio.effect.LoudnessEnhancer.Capability loudnessEnhancer;
-  android.hardware.audio.effect.Reverb.Capability reverb;
+  android.hardware.audio.effect.PresetReverb.Capability presetReverb;
   android.hardware.audio.effect.Virtualizer.Capability virtualizer;
   android.hardware.audio.effect.Visualizer.Capability visualizer;
   android.hardware.audio.effect.Volume.Capability volume;
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl
similarity index 95%
rename from audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
rename to audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl
index 8ad4848..fcf08c3 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.audio.effect;
 @VintfStability
-union Reverb {
+union EnvironmentalReverb {
   android.hardware.audio.effect.VendorExtension vendor;
   int roomLevelMb;
   int roomHfLevelMb;
@@ -47,7 +47,7 @@
   @VintfStability
   union Id {
     int vendorExtensionTag;
-    android.hardware.audio.effect.Reverb.Tag commonTag;
+    android.hardware.audio.effect.EnvironmentalReverb.Tag commonTag;
   }
   @VintfStability
   parcelable Capability {
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl
index 5b85d33..a6c138c 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl
@@ -34,7 +34,7 @@
 package android.hardware.audio.effect;
 @VintfStability
 interface IFactory {
-  android.hardware.audio.effect.Descriptor.Identity[] queryEffects(in @nullable android.media.audio.common.AudioUuid type, in @nullable android.media.audio.common.AudioUuid implementation, in @nullable android.media.audio.common.AudioUuid proxy);
+  android.hardware.audio.effect.Descriptor[] queryEffects(in @nullable android.media.audio.common.AudioUuid type, in @nullable android.media.audio.common.AudioUuid implementation, in @nullable android.media.audio.common.AudioUuid proxy);
   android.hardware.audio.effect.Processing[] queryProcessing(in @nullable android.hardware.audio.effect.Processing.Type type);
   android.hardware.audio.effect.IEffect createEffect(in android.media.audio.common.AudioUuid implUuid);
   void destroyEffect(in android.hardware.audio.effect.IEffect handle);
diff --git a/audio/aidl/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 321c286..0635c13 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
@@ -46,10 +46,11 @@
     android.hardware.audio.effect.BassBoost.Id bassBoostTag;
     android.hardware.audio.effect.Downmix.Id downmixTag;
     android.hardware.audio.effect.DynamicsProcessing.Id dynamicsProcessingTag;
+    android.hardware.audio.effect.EnvironmentalReverb.Id environmentalReverbTag;
     android.hardware.audio.effect.Equalizer.Id equalizerTag;
     android.hardware.audio.effect.HapticGenerator.Id hapticGeneratorTag;
     android.hardware.audio.effect.LoudnessEnhancer.Id loudnessEnhancerTag;
-    android.hardware.audio.effect.Reverb.Id reverbTag;
+    android.hardware.audio.effect.PresetReverb.Id presetReverbTag;
     android.hardware.audio.effect.Virtualizer.Id virtualizerTag;
     android.hardware.audio.effect.Visualizer.Id visualizerTag;
     android.hardware.audio.effect.Volume.Id volumeTag;
@@ -73,10 +74,11 @@
     android.hardware.audio.effect.BassBoost bassBoost;
     android.hardware.audio.effect.Downmix downmix;
     android.hardware.audio.effect.DynamicsProcessing dynamicsProcessing;
+    android.hardware.audio.effect.EnvironmentalReverb environmentalReverb;
     android.hardware.audio.effect.Equalizer equalizer;
-    android.hardware.audio.effect.LoudnessEnhancer loudnessEnhancer;
     android.hardware.audio.effect.HapticGenerator hapticGenerator;
-    android.hardware.audio.effect.Reverb reverb;
+    android.hardware.audio.effect.LoudnessEnhancer loudnessEnhancer;
+    android.hardware.audio.effect.PresetReverb presetReverb;
     android.hardware.audio.effect.Virtualizer virtualizer;
     android.hardware.audio.effect.Visualizer visualizer;
     android.hardware.audio.effect.Volume volume;
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/PresetReverb.aidl
similarity index 83%
copy from audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
copy to audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/PresetReverb.aidl
index 8ad4848..24a9ce1 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/PresetReverb.aidl
@@ -33,25 +33,27 @@
 
 package android.hardware.audio.effect;
 @VintfStability
-union Reverb {
+union PresetReverb {
   android.hardware.audio.effect.VendorExtension vendor;
-  int roomLevelMb;
-  int roomHfLevelMb;
-  int decayTimeMs;
-  int decayHfRatioPm;
-  int levelMb;
-  int delayMs;
-  int diffusionPm;
-  int densityPm;
-  boolean bypass;
+  android.hardware.audio.effect.PresetReverb.Presets preset;
+  @Backing(type="int") @VintfStability
+  enum Presets {
+    NONE = 0,
+    SMALLROOM = 1,
+    MEDIUMROOM = 2,
+    LARGEROOM = 3,
+    MEDIUMHALL = 4,
+    LARGEHALL = 5,
+    PLATE = 6,
+  }
   @VintfStability
   union Id {
     int vendorExtensionTag;
-    android.hardware.audio.effect.Reverb.Tag commonTag;
+    android.hardware.audio.effect.PresetReverb.Tag commonTag;
   }
   @VintfStability
   parcelable Capability {
     android.hardware.audio.effect.VendorExtension extension;
-    int maxDecayTimeMs;
+    android.hardware.audio.effect.PresetReverb.Presets[] supportedPresets;
   }
 }
diff --git a/audio/aidl/android/hardware/audio/core/IConfig.aidl b/audio/aidl/android/hardware/audio/core/IConfig.aidl
index c8ba6be..094d233 100644
--- a/audio/aidl/android/hardware/audio/core/IConfig.aidl
+++ b/audio/aidl/android/hardware/audio/core/IConfig.aidl
@@ -17,6 +17,7 @@
 package android.hardware.audio.core;
 
 import android.hardware.audio.core.SurroundSoundConfig;
+import android.media.audio.common.AudioHalEngineConfig;
 
 /**
  * This interface provides system-wide configuration parameters for audio I/O
@@ -34,4 +35,19 @@
      * @return The surround sound configuration
      */
     SurroundSoundConfig getSurroundSoundConfig();
+    /**
+     * Returns the configuration items used to determine the audio policy engine
+     * flavor and initial configuration.
+     *
+     * Engine flavor is determined by presence of capSpecificConfig, which must
+     * only be present if the device uses the Configurable Audio Policy (CAP)
+     * engine. Clients normally use the default audio policy engine. The client
+     * will use the CAP engine only when capSpecificConfig has a non-null value.
+     *
+     * This method is expected to only be called during the initialization of
+     * the audio policy engine, and must always return the same result.
+     *
+     * @return The engine configuration
+     */
+    AudioHalEngineConfig getEngineConfig();
 }
diff --git a/audio/aidl/android/hardware/audio/effect/BassBoost.aidl b/audio/aidl/android/hardware/audio/effect/BassBoost.aidl
index 810c188..9e5d8aa 100644
--- a/audio/aidl/android/hardware/audio/effect/BassBoost.aidl
+++ b/audio/aidl/android/hardware/audio/effect/BassBoost.aidl
@@ -59,6 +59,16 @@
     }
 
     /**
+     * Minimal possible per mille strength.
+     */
+    const int MIN_PER_MILLE_STRENGTH = 0;
+
+    /**
+     * Maximum possible per mille strength.
+     */
+    const int MAX_PER_MILLE_STRENGTH = 1000;
+
+    /**
      * The per mille strength of the bass boost effect.
      *
      * If the implementation does not support per mille accuracy for setting the strength, it is
diff --git a/audio/aidl/android/hardware/audio/effect/Capability.aidl b/audio/aidl/android/hardware/audio/effect/Capability.aidl
index f741f33..4149783 100644
--- a/audio/aidl/android/hardware/audio/effect/Capability.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Capability.aidl
@@ -19,10 +19,11 @@
 import android.hardware.audio.effect.BassBoost;
 import android.hardware.audio.effect.Downmix;
 import android.hardware.audio.effect.DynamicsProcessing;
+import android.hardware.audio.effect.EnvironmentalReverb;
 import android.hardware.audio.effect.Equalizer;
 import android.hardware.audio.effect.HapticGenerator;
 import android.hardware.audio.effect.LoudnessEnhancer;
-import android.hardware.audio.effect.Reverb;
+import android.hardware.audio.effect.PresetReverb;
 import android.hardware.audio.effect.VendorExtension;
 import android.hardware.audio.effect.Virtualizer;
 import android.hardware.audio.effect.Visualizer;
@@ -51,10 +52,11 @@
     BassBoost.Capability bassBoost;
     Downmix.Capability downmix;
     DynamicsProcessing.Capability dynamicsProcessing;
+    EnvironmentalReverb.Capability environmentalReverb;
     Equalizer.Capability equalizer;
     HapticGenerator.Capability hapticGenerator;
     LoudnessEnhancer.Capability loudnessEnhancer;
-    Reverb.Capability reverb;
+    PresetReverb.Capability presetReverb;
     Virtualizer.Capability virtualizer;
     Visualizer.Capability visualizer;
     Volume.Capability volume;
diff --git a/audio/aidl/android/hardware/audio/effect/Reverb.aidl b/audio/aidl/android/hardware/audio/effect/EnvironmentalReverb.aidl
similarity index 82%
rename from audio/aidl/android/hardware/audio/effect/Reverb.aidl
rename to audio/aidl/android/hardware/audio/effect/EnvironmentalReverb.aidl
index f60c2ea..3df0d27 100644
--- a/audio/aidl/android/hardware/audio/effect/Reverb.aidl
+++ b/audio/aidl/android/hardware/audio/effect/EnvironmentalReverb.aidl
@@ -19,24 +19,26 @@
 import android.hardware.audio.effect.VendorExtension;
 
 /**
- * Reverb specific definitions.
+ * Environmental Reverb specific definitions.
  *
- * All parameters defined in union Reverb must be gettable and settable. The capabilities defined in
- * Reverb.Capability can only acquired with IEffect.getDescriptor() and not settable.
+ * All parameters defined in union Environmental must be gettable and settable. The capabilities
+ * * defined in EnvironmentalReverb.Capability can only acquired with IEffect.getDescriptor() and
+ * not * settable.
  */
+
 @VintfStability
-union Reverb {
+union EnvironmentalReverb {
     /**
      * Effect parameter tag to identify the parameters for getParameter().
      */
     @VintfStability
     union Id {
         int vendorExtensionTag;
-        Reverb.Tag commonTag;
+        EnvironmentalReverb.Tag commonTag;
     }
 
     /**
-     * Vendor Reverb implementation definition for additional parameters.
+     * Vendor EnvironmentalReverb implementation definition for additional parameters.
      */
     VendorExtension vendor;
 
diff --git a/audio/aidl/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
index 5943359..b80e6ac 100644
--- a/audio/aidl/android/hardware/audio/effect/IFactory.aidl
+++ b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
@@ -31,8 +31,8 @@
 @VintfStability
 interface IFactory {
     /**
-     * Return a list of effect identities supported by this device, with the optional
-     * filter by type and/or by instance UUID.
+     * Return a list of effect descriptors supported by this device, with the optional filter by
+     * type and/or by instance UUID.
      *
      * @param type UUID identifying the effect type.
      *        This is an optional parameter, pass in null if this parameter is not necessary; if non
@@ -43,9 +43,9 @@
      * @param proxy Indicates the proxy UUID filter to query.
      *        This is an optional parameter, pass in null if this parameter is not necessary; if
      *        non null, used as a filter for effect proxy UUIDs.
-     * @return List of effect identities supported and filtered by type/implementation UUID.
+     * @return List of effect Descriptors supported and filtered by type/implementation/proxy UUID.
      */
-    Descriptor.Identity[] queryEffects(in @nullable AudioUuid type,
+    Descriptor[] queryEffects(in @nullable AudioUuid type,
             in @nullable AudioUuid implementation, in @nullable AudioUuid proxy);
 
     /**
diff --git a/audio/aidl/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/android/hardware/audio/effect/Parameter.aidl
index e7d3d5e..d7a6a27 100644
--- a/audio/aidl/android/hardware/audio/effect/Parameter.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Parameter.aidl
@@ -19,10 +19,11 @@
 import android.hardware.audio.effect.BassBoost;
 import android.hardware.audio.effect.Downmix;
 import android.hardware.audio.effect.DynamicsProcessing;
+import android.hardware.audio.effect.EnvironmentalReverb;
 import android.hardware.audio.effect.Equalizer;
 import android.hardware.audio.effect.HapticGenerator;
 import android.hardware.audio.effect.LoudnessEnhancer;
-import android.hardware.audio.effect.Reverb;
+import android.hardware.audio.effect.PresetReverb;
 import android.hardware.audio.effect.VendorExtension;
 import android.hardware.audio.effect.Virtualizer;
 import android.hardware.audio.effect.Visualizer;
@@ -73,10 +74,11 @@
         BassBoost.Id bassBoostTag;
         Downmix.Id downmixTag;
         DynamicsProcessing.Id dynamicsProcessingTag;
+        EnvironmentalReverb.Id environmentalReverbTag;
         Equalizer.Id equalizerTag;
         HapticGenerator.Id hapticGeneratorTag;
         LoudnessEnhancer.Id loudnessEnhancerTag;
-        Reverb.Id reverbTag;
+        PresetReverb.Id presetReverbTag;
         Virtualizer.Id virtualizerTag;
         Visualizer.Id visualizerTag;
         Volume.Id volumeTag;
@@ -150,10 +152,11 @@
         BassBoost bassBoost;
         Downmix downmix;
         DynamicsProcessing dynamicsProcessing;
+        EnvironmentalReverb environmentalReverb;
         Equalizer equalizer;
-        LoudnessEnhancer loudnessEnhancer;
         HapticGenerator hapticGenerator;
-        Reverb reverb;
+        LoudnessEnhancer loudnessEnhancer;
+        PresetReverb presetReverb;
         Virtualizer virtualizer;
         Visualizer visualizer;
         Volume volume;
diff --git a/audio/aidl/android/hardware/audio/effect/PresetReverb.aidl b/audio/aidl/android/hardware/audio/effect/PresetReverb.aidl
new file mode 100644
index 0000000..6048eea
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/PresetReverb.aidl
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+
+/**
+ * PresetReverb specific definitions.
+ *
+ * All parameters defined in union PresetReverb must be gettable and settable. The capabilities
+ * defined in PresetReverb.Capability can only acquired with IEffect.getDescriptor() and not
+ * settable.
+ */
+@VintfStability
+union PresetReverb {
+    /**
+     * Presets enum definition.
+     */
+    @VintfStability
+    @Backing(type="int")
+    enum Presets {
+        /**
+         * No reverb or reflections
+         */
+        NONE,
+        /**
+         * A small room less than five meters in length
+         */
+        SMALLROOM,
+        /**
+         * A medium room with a length of ten meters or less.
+         */
+        MEDIUMROOM,
+        /**
+         * A large-sized room suitable for live performances.
+         */
+        LARGEROOM,
+        /**
+         * A medium-sized hall.
+         */
+        MEDIUMHALL,
+        /**
+         * a large-sized hall suitable for a full orchestra.
+         */
+        LARGEHALL,
+        /**
+         * Synthesis of the traditional plate reverb.
+         */
+        PLATE,
+    }
+
+    /**
+     * Effect parameter tag to identify the parameters for getParameter().
+     */
+    @VintfStability
+    union Id {
+        int vendorExtensionTag;
+        PresetReverb.Tag commonTag;
+    }
+
+    /**
+     * Vendor PresetReverb implementation definition for additional parameters.
+     */
+    VendorExtension vendor;
+
+    /**
+     * Capability supported by effect implementation.
+     */
+    @VintfStability
+    parcelable Capability {
+        VendorExtension extension;
+
+        /**
+         * List of presets supported.
+         */
+        Presets[] supportedPresets;
+    }
+
+    /**
+     * Get current reverb preset when used in getParameter.
+     * Enable a preset reverb when used in setParameter.
+     */
+    Presets preset;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/state.gv b/audio/aidl/android/hardware/audio/effect/state.gv
index e19e6c7..c88521e 100644
--- a/audio/aidl/android/hardware/audio/effect/state.gv
+++ b/audio/aidl/android/hardware/audio/effect/state.gv
@@ -16,21 +16,21 @@
 
 // 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;
+    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="open()" labelfontcolor="lime"];
-    IDLE -> PROCESSING [label="command(START"];
-    PROCESSING -> IDLE [label="command(STOP)\ncommand(RESET)"];
-    IDLE -> INIT [label="close()"];
+    I -> INIT[label = "IFactory.createEffect" labelfontcolor = "navy"];
+    INIT -> F[label = "IFactory.destroyEffect"];
+    INIT -> IDLE[label = "open()" labelfontcolor = "lime"];
+    IDLE -> PROCESSING[label = "command(START"];
+    PROCESSING -> IDLE[label = "command(STOP)\ncommand(RESET)"];
+    IDLE -> INIT[label = "close()"];
 
-    INIT -> INIT [label="getState\ngetDescriptor"];
-    IDLE -> IDLE [label="getXXX\nsetParameter\ncommand(RESET)"];
-    PROCESSING -> PROCESSING [label="getXXX\nsetParameter"];
-}
\ No newline at end of file
+    INIT -> INIT[label = "getState\ngetDescriptor"];
+    IDLE -> IDLE[label = "getXXX\nsetParameter\ncommand(RESET)"];
+    PROCESSING -> PROCESSING[label = "getXXX\nsetParameter"];
+}
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
index 1026134..990cff9 100644
--- a/audio/aidl/common/include/Utils.h
+++ b/audio/aidl/common/include/Utils.h
@@ -20,6 +20,7 @@
 #include <type_traits>
 
 #include <aidl/android/media/audio/common/AudioChannelLayout.h>
+#include <aidl/android/media/audio/common/AudioDeviceType.h>
 #include <aidl/android/media/audio/common/AudioFormatDescription.h>
 #include <aidl/android/media/audio/common/AudioInputFlags.h>
 #include <aidl/android/media/audio/common/AudioOutputFlags.h>
@@ -83,6 +84,12 @@
     return 0;
 }
 
+constexpr bool isTelephonyDeviceType(
+        ::aidl::android::media::audio::common::AudioDeviceType device) {
+    return device == ::aidl::android::media::audio::common::AudioDeviceType::IN_TELEPHONY_RX ||
+           device == ::aidl::android::media::audio::common::AudioDeviceType::OUT_TELEPHONY_TX;
+}
+
 // The helper functions defined below are only applicable to the case when an enum type
 // specifies zero-based bit positions, not bit masks themselves. This is why instantiation
 // is restricted to certain enum types.
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 2b9ed5b..f2cebbf 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -18,11 +18,14 @@
         "libfmq",
         "libstagefright_foundation",
         "libutils",
+        "libxml2",
         "android.hardware.common-V2-ndk",
         "android.hardware.common.fmq-V1-ndk",
     ],
     header_libs: [
+        "libaudio_system_headers",
         "libaudioaidl_headers",
+        "libxsdc-utils",
     ],
 }
 
@@ -35,12 +38,26 @@
     ],
     export_include_dirs: ["include"],
     srcs: [
+        "AudioPolicyConfigXmlConverter.cpp",
         "Config.cpp",
         "Configuration.cpp",
+        "EngineConfigXmlConverter.cpp",
         "Module.cpp",
         "Stream.cpp",
         "Telephony.cpp",
     ],
+    generated_sources: [
+        "audio_policy_configuration_aidl_default",
+        "audio_policy_engine_configuration_aidl_default",
+    ],
+    generated_headers: [
+        "audio_policy_configuration_aidl_default",
+        "audio_policy_engine_configuration_aidl_default",
+    ],
+    export_generated_headers: [
+        "audio_policy_configuration_aidl_default",
+        "audio_policy_engine_configuration_aidl_default",
+    ],
     visibility: [
         ":__subpackages__",
     ],
diff --git a/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp b/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp
new file mode 100644
index 0000000..6290912
--- /dev/null
+++ b/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+#include <functional>
+#include <unordered_map>
+
+#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
+#include <system/audio-base-utils.h>
+
+#include "core-impl/AudioPolicyConfigXmlConverter.h"
+
+using aidl::android::media::audio::common::AudioHalEngineConfig;
+using aidl::android::media::audio::common::AudioHalVolumeCurve;
+using aidl::android::media::audio::common::AudioHalVolumeGroup;
+using aidl::android::media::audio::common::AudioStreamType;
+
+namespace xsd = android::audio::policy::configuration;
+
+namespace aidl::android::hardware::audio::core::internal {
+
+static const int kDefaultVolumeIndexMin = 0;
+static const int kDefaultVolumeIndexMax = 100;
+static const int KVolumeIndexDeferredToAudioService = -1;
+/**
+ * Valid curve points take the form "<index>,<attenuationMb>", where the index
+ * must be in the range [0,100]. kInvalidCurvePointIndex is used to indicate
+ * that a point was formatted incorrectly (e.g. if a vendor accidentally typed a
+ * '.' instead of a ',' in their XML) -- using such a curve point will result in
+ * failed VTS tests.
+ */
+static const int8_t kInvalidCurvePointIndex = -1;
+
+AudioHalVolumeCurve::CurvePoint AudioPolicyConfigXmlConverter::convertCurvePointToAidl(
+        const std::string& xsdcCurvePoint) {
+    AudioHalVolumeCurve::CurvePoint aidlCurvePoint{};
+    if (sscanf(xsdcCurvePoint.c_str(), "%" SCNd8 ",%d", &aidlCurvePoint.index,
+               &aidlCurvePoint.attenuationMb) != 2) {
+        aidlCurvePoint.index = kInvalidCurvePointIndex;
+    }
+    return aidlCurvePoint;
+}
+
+AudioHalVolumeCurve AudioPolicyConfigXmlConverter::convertVolumeCurveToAidl(
+        const xsd::Volume& xsdcVolumeCurve) {
+    AudioHalVolumeCurve aidlVolumeCurve;
+    aidlVolumeCurve.deviceCategory =
+            static_cast<AudioHalVolumeCurve::DeviceCategory>(xsdcVolumeCurve.getDeviceCategory());
+    if (xsdcVolumeCurve.hasRef()) {
+        if (mVolumesReferenceMap.empty()) {
+            mVolumesReferenceMap = generateReferenceMap<xsd::Volumes, xsd::Reference>(
+                    getXsdcConfig()->getVolumes());
+        }
+        aidlVolumeCurve.curvePoints =
+                convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+                        mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
+                        std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this,
+                                  std::placeholders::_1));
+    } else {
+        aidlVolumeCurve.curvePoints =
+                convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+                        xsdcVolumeCurve.getPoint(),
+                        std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this,
+                                  std::placeholders::_1));
+    }
+    return aidlVolumeCurve;
+}
+
+void AudioPolicyConfigXmlConverter::mapStreamToVolumeCurve(const xsd::Volume& xsdcVolumeCurve) {
+    mStreamToVolumeCurvesMap[xsdcVolumeCurve.getStream()].push_back(
+            convertVolumeCurveToAidl(xsdcVolumeCurve));
+}
+
+const AudioHalEngineConfig& AudioPolicyConfigXmlConverter::getAidlEngineConfig() {
+    if (mAidlEngineConfig.volumeGroups.empty() && getXsdcConfig() &&
+        getXsdcConfig()->hasVolumes()) {
+        parseVolumes();
+    }
+    return mAidlEngineConfig;
+}
+
+void AudioPolicyConfigXmlConverter::mapStreamsToVolumeCurves() {
+    if (getXsdcConfig()->hasVolumes()) {
+        for (const xsd::Volumes& xsdcWrapperType : getXsdcConfig()->getVolumes()) {
+            for (const xsd::Volume& xsdcVolume : xsdcWrapperType.getVolume()) {
+                mapStreamToVolumeCurve(xsdcVolume);
+            }
+        }
+    }
+}
+
+void AudioPolicyConfigXmlConverter::addVolumeGroupstoEngineConfig() {
+    for (const auto& [xsdcStream, volumeCurves] : mStreamToVolumeCurvesMap) {
+        AudioHalVolumeGroup volumeGroup;
+        volumeGroup.name = xsd::toString(xsdcStream);
+        if (static_cast<int>(xsdcStream) >= AUDIO_STREAM_PUBLIC_CNT) {
+            volumeGroup.minIndex = kDefaultVolumeIndexMin;
+            volumeGroup.maxIndex = kDefaultVolumeIndexMax;
+        } else {
+            volumeGroup.minIndex = KVolumeIndexDeferredToAudioService;
+            volumeGroup.maxIndex = KVolumeIndexDeferredToAudioService;
+        }
+        volumeGroup.volumeCurves = volumeCurves;
+        mAidlEngineConfig.volumeGroups.push_back(std::move(volumeGroup));
+    }
+}
+
+void AudioPolicyConfigXmlConverter::parseVolumes() {
+    if (mStreamToVolumeCurvesMap.empty() && getXsdcConfig()->hasVolumes()) {
+        mapStreamsToVolumeCurves();
+        addVolumeGroupstoEngineConfig();
+    }
+}
+}  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/Config.cpp b/audio/aidl/default/Config.cpp
index 0fdd5b4..87c0ace 100644
--- a/audio/aidl/default/Config.cpp
+++ b/audio/aidl/default/Config.cpp
@@ -13,10 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define LOG_TAG "AHAL_Module"
+
+#define LOG_TAG "AHAL_Config"
 #include <android-base/logging.h>
 
+#include <system/audio_config.h>
+
+#include "core-impl/AudioPolicyConfigXmlConverter.h"
 #include "core-impl/Config.h"
+#include "core-impl/EngineConfigXmlConverter.h"
+
+using aidl::android::media::audio::common::AudioHalEngineConfig;
 
 namespace aidl::android::hardware::audio::core {
 ndk::ScopedAStatus Config::getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) {
@@ -26,4 +33,24 @@
     LOG(DEBUG) << __func__ << ": returning " << _aidl_return->toString();
     return ndk::ScopedAStatus::ok();
 }
+
+ndk::ScopedAStatus Config::getEngineConfig(AudioHalEngineConfig* _aidl_return) {
+    static const AudioHalEngineConfig returnEngCfg = [this]() {
+        AudioHalEngineConfig engConfig;
+        if (mEngConfigConverter.getStatus() == ::android::OK) {
+            engConfig = mEngConfigConverter.getAidlEngineConfig();
+        } else {
+            LOG(INFO) << __func__ << mEngConfigConverter.getError();
+            if (mAudioPolicyConverter.getStatus() == ::android::OK) {
+                engConfig = mAudioPolicyConverter.getAidlEngineConfig();
+            } else {
+                LOG(WARNING) << __func__ << mAudioPolicyConverter.getError();
+            }
+        }
+        return engConfig;
+    }();
+    *_aidl_return = returnEngCfg;
+    LOG(DEBUG) << __func__ << ": returning " << _aidl_return->toString();
+    return ndk::ScopedAStatus::ok();
+}
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index 280814f..6d5357b 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -115,85 +115,150 @@
     return config;
 }
 
-static AudioRoute createRoute(const std::vector<int32_t>& sources, int32_t sink) {
+static AudioRoute createRoute(const std::vector<AudioPort>& sources, const AudioPort& sink) {
     AudioRoute route;
-    route.sinkPortId = sink;
-    route.sourcePortIds.insert(route.sourcePortIds.end(), sources.begin(), sources.end());
+    route.sinkPortId = sink.id;
+    std::transform(sources.begin(), sources.end(), std::back_inserter(route.sourcePortIds),
+                   [](const auto& port) { return port.id; });
     return route;
 }
 
-// Configuration:
+// Primary (default) configuration:
 //
 // Device ports:
-//  * "Null", OUT_SPEAKER, default
+//  * "Speaker", OUT_SPEAKER, default
 //    - no profiles specified
-//  * "Loopback Out", OUT_SUBMIX
-//    - profile PCM 24-bit; STEREO; 48000
+//  * "Built-in Mic", IN_MICROPHONE, default
+//    - no profiles specified
+//  * "Telephony Tx", OUT_TELEPHONY_TX
+//    - no profiles specified
+//  * "Telephony Rx", IN_TELEPHONY_RX
+//    - no profiles specified
+//  * "FM Tuner", IN_FM_TUNER
+//    - no profiles specified
 //  * "USB Out", OUT_DEVICE, CONNECTION_USB
 //    - no profiles specified
-//  * "Zero", IN_MICROPHONE, default
-//    - no profiles specified
-//  * "Loopback In", IN_SUBMIX
-//    - profile PCM 24-bit; STEREO; 48000
 //  * "USB In", IN_DEVICE, CONNECTION_USB
 //    - no profiles specified
 //
 // Mix ports:
 //  * "primary output", PRIMARY, 1 max open, 1 max active stream
-//    - profile PCM 16-bit; MONO, STEREO; 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 44100, 48000
+//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //  * "compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active stream
 //    - profile MP3; MONO, STEREO; 44100, 48000
-//  * "loopback output", stream count unlimited
-//    - profile PCM 24-bit; STEREO; 48000
 //  * "primary input", 2 max open, 2 max active streams
 //    - profile PCM 16-bit; MONO, STEREO, FRONT_BACK;
 //        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
 //    - profile PCM 24-bit; MONO, STEREO, FRONT_BACK;
 //        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
-//  * "loopback input", stream count unlimited
-//    - profile PCM 24-bit; STEREO; 48000
+//  * "telephony_tx", 1 max open, 1 max active stream
+//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//  * "telephony_rx", 1 max open, 1 max active stream
+//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//  * "fm_tuner", 1 max open, 1 max active stream
+//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //
 // Routes:
-//  "primary out", "compressed offload" -> "Null"
+//  "primary out", "compressed offload" -> "Speaker"
 //  "primary out", "compressed offload" -> "USB Out"
-//  "loopback out" -> "Loopback Out"
-//  "Zero", "USB In" -> "primary input"
-//  "Loopback In" -> "loopback input"
+//  "Built-in Mic", "USB In" -> "primary input"
+//  "telephony_tx" -> "Telephony Tx"
+//  "Telephony Rx" -> "telephony_rx"
+//  "FM Tuner" -> "fm_tuner"
 //
 // Initial port configs:
-//  * "Null" device port: PCM 24-bit; STEREO; 48000
-//  * "Zero" device port: PCM 24-bit; MONO; 48000
+//  * "Speaker" device port: PCM 24-bit; STEREO; 48000
+//  * "Built-in Mic" device port: PCM 24-bit; MONO; 48000
+//  * "Telephony Tx" device port: PCM 24-bit; MONO; 48000
+//  * "Telephony Rx" device port: PCM 24-bit; MONO; 48000
+//  * "FM Tuner" device port: PCM 24-bit; STEREO; 48000
 //
 // Profiles for device port connected state:
 //  * USB Out":
-//    - profile PCM 16-bit; MONO, STEREO; 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 44100, 48000
+//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //  * USB In":
-//    - profile PCM 16-bit; MONO, STEREO; 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 44100, 48000
+//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //
-Configuration& getNullPrimaryConfiguration() {
-    static Configuration configuration = []() {
+std::unique_ptr<Configuration> getPrimaryConfiguration() {
+    static const Configuration configuration = []() {
         const std::vector<AudioProfile> standardPcmAudioProfiles = {
                 createProfile(PcmType::INT_16_BIT,
                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
-                              {44100, 48000}),
+                              {8000, 11025, 16000, 32000, 44100, 48000}),
                 createProfile(PcmType::INT_24_BIT,
                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
-                              {44100, 48000})};
+                              {8000, 11025, 16000, 32000, 44100, 48000})};
         Configuration c;
 
-        AudioPort nullOutDevice =
-                createPort(c.nextPortId++, "Null", 0, false,
+        // Device ports
+
+        AudioPort speakerOutDevice =
+                createPort(c.nextPortId++, "Speaker", 0, false,
                            createDeviceExt(AudioDeviceType::OUT_SPEAKER,
                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
-        c.ports.push_back(nullOutDevice);
+        c.ports.push_back(speakerOutDevice);
         c.initialConfigs.push_back(
-                createPortConfig(nullOutDevice.id, nullOutDevice.id, PcmType::INT_24_BIT,
+                createPortConfig(speakerOutDevice.id, speakerOutDevice.id, PcmType::INT_24_BIT,
                                  AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
                                  createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
 
+        AudioPort micInDevice =
+                createPort(c.nextPortId++, "Built-in Mic", 0, true,
+                           createDeviceExt(AudioDeviceType::IN_MICROPHONE,
+                                           1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
+        c.ports.push_back(micInDevice);
+        c.initialConfigs.push_back(
+                createPortConfig(micInDevice.id, micInDevice.id, PcmType::INT_24_BIT,
+                                 AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
+                                 createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
+
+        AudioPort telephonyTxOutDevice =
+                createPort(c.nextPortId++, "Telephony Tx", 0, false,
+                           createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0));
+        c.ports.push_back(telephonyTxOutDevice);
+        c.initialConfigs.push_back(
+                createPortConfig(telephonyTxOutDevice.id, telephonyTxOutDevice.id,
+                                 PcmType::INT_24_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
+                                 false, createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0)));
+
+        AudioPort telephonyRxInDevice =
+                createPort(c.nextPortId++, "Telephony Rx", 0, true,
+                           createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0));
+        c.ports.push_back(telephonyRxInDevice);
+        c.initialConfigs.push_back(
+                createPortConfig(telephonyRxInDevice.id, telephonyRxInDevice.id,
+                                 PcmType::INT_24_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
+                                 true, createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0)));
+
+        AudioPort fmTunerInDevice = createPort(c.nextPortId++, "FM Tuner", 0, true,
+                                               createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0));
+        c.ports.push_back(fmTunerInDevice);
+        c.initialConfigs.push_back(
+                createPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, PcmType::INT_24_BIT,
+                                 AudioChannelLayout::LAYOUT_STEREO, 48000, 0, true,
+                                 createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0)));
+
+        AudioPort usbOutDevice =
+                createPort(c.nextPortId++, "USB Out", 0, false,
+                           createDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
+                                           AudioDeviceDescription::CONNECTION_USB));
+        c.ports.push_back(usbOutDevice);
+        c.connectedProfiles[usbOutDevice.id] = standardPcmAudioProfiles;
+
+        AudioPort usbInDevice = createPort(c.nextPortId++, "USB In", 0, true,
+                                           createDeviceExt(AudioDeviceType::IN_DEVICE, 0,
+                                                           AudioDeviceDescription::CONNECTION_USB));
+        c.ports.push_back(usbInDevice);
+        c.connectedProfiles[usbInDevice.id] = standardPcmAudioProfiles;
+
+        // Mix ports
+
         AudioPort primaryOutMix = createPort(c.nextPortId++, "primary output",
                                              makeBitPositionFlagMask(AudioOutputFlags::PRIMARY),
                                              false, createPortMixExt(1, 1));
@@ -214,42 +279,6 @@
                               {44100, 48000}));
         c.ports.push_back(compressedOffloadOutMix);
 
-        AudioPort loopOutDevice = createPort(c.nextPortId++, "Loopback Out", 0, false,
-                                             createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0));
-        loopOutDevice.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
-        c.ports.push_back(loopOutDevice);
-
-        AudioPort loopOutMix =
-                createPort(c.nextPortId++, "loopback output", 0, false, createPortMixExt(0, 0));
-        loopOutMix.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
-        c.ports.push_back(loopOutMix);
-
-        AudioPort usbOutDevice =
-                createPort(c.nextPortId++, "USB Out", 0, false,
-                           createDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
-                                           AudioDeviceDescription::CONNECTION_USB));
-        c.ports.push_back(usbOutDevice);
-        c.connectedProfiles[usbOutDevice.id] = standardPcmAudioProfiles;
-
-        AudioPort zeroInDevice =
-                createPort(c.nextPortId++, "Zero", 0, true,
-                           createDeviceExt(AudioDeviceType::IN_MICROPHONE,
-                                           1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
-        c.ports.push_back(zeroInDevice);
-        c.initialConfigs.push_back(
-                createPortConfig(zeroInDevice.id, zeroInDevice.id, PcmType::INT_24_BIT,
-                                 AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
-                                 createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
-
-        MicrophoneInfo mic;
-        mic.id = "zero";
-        mic.device = zeroInDevice.ext.get<AudioPortExt::Tag::device>().device;
-        mic.group = 0;
-        mic.indexInTheGroup = 0;
-        c.microphones = std::vector<MicrophoneInfo>{mic};
-
         AudioPort primaryInMix =
                 createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(2, 2));
         primaryInMix.profiles.push_back(
@@ -264,36 +293,104 @@
                               {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
         c.ports.push_back(primaryInMix);
 
-        AudioPort loopInDevice = createPort(c.nextPortId++, "Loopback In", 0, true,
-                                            createDeviceExt(AudioDeviceType::IN_SUBMIX, 0));
-        loopInDevice.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
-        c.ports.push_back(loopInDevice);
+        AudioPort telephonyTxOutMix =
+                createPort(c.nextPortId++, "telephony_tx", 0, false, createPortMixExt(1, 1));
+        telephonyTxOutMix.profiles.insert(telephonyTxOutMix.profiles.begin(),
+                                          standardPcmAudioProfiles.begin(),
+                                          standardPcmAudioProfiles.end());
+        c.ports.push_back(telephonyTxOutMix);
 
-        AudioPort loopInMix =
-                createPort(c.nextPortId++, "loopback input", 0, true, createPortMixExt(0, 0));
-        loopInMix.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
-        c.ports.push_back(loopInMix);
+        AudioPort telephonyRxInMix =
+                createPort(c.nextPortId++, "telephony_rx", 0, true, createPortMixExt(1, 1));
+        telephonyRxInMix.profiles.insert(telephonyRxInMix.profiles.begin(),
+                                         standardPcmAudioProfiles.begin(),
+                                         standardPcmAudioProfiles.end());
+        c.ports.push_back(telephonyRxInMix);
 
-        AudioPort usbInDevice = createPort(c.nextPortId++, "USB In", 0, true,
-                                           createDeviceExt(AudioDeviceType::IN_DEVICE, 0,
-                                                           AudioDeviceDescription::CONNECTION_USB));
-        c.ports.push_back(usbInDevice);
-        c.connectedProfiles[usbInDevice.id] = standardPcmAudioProfiles;
+        AudioPort fmTunerInMix =
+                createPort(c.nextPortId++, "fm_tuner", 0, true, createPortMixExt(1, 1));
+        fmTunerInMix.profiles.insert(fmTunerInMix.profiles.begin(),
+                                     standardPcmAudioProfiles.begin(),
+                                     standardPcmAudioProfiles.end());
+        c.ports.push_back(fmTunerInMix);
 
-        c.routes.push_back(
-                createRoute({primaryOutMix.id, compressedOffloadOutMix.id}, nullOutDevice.id));
-        c.routes.push_back(
-                createRoute({primaryOutMix.id, compressedOffloadOutMix.id}, usbOutDevice.id));
-        c.routes.push_back(createRoute({loopOutMix.id}, loopOutDevice.id));
-        c.routes.push_back(createRoute({zeroInDevice.id, usbInDevice.id}, primaryInMix.id));
-        c.routes.push_back(createRoute({loopInDevice.id}, loopInMix.id));
+        c.routes.push_back(createRoute({primaryOutMix, compressedOffloadOutMix}, speakerOutDevice));
+        c.routes.push_back(createRoute({primaryOutMix, compressedOffloadOutMix}, usbOutDevice));
+        c.routes.push_back(createRoute({micInDevice, usbInDevice}, primaryInMix));
+        c.routes.push_back(createRoute({telephonyTxOutMix}, telephonyTxOutDevice));
+        c.routes.push_back(createRoute({telephonyRxInDevice}, telephonyRxInMix));
+        c.routes.push_back(createRoute({fmTunerInDevice}, fmTunerInMix));
 
         c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
+
+        MicrophoneInfo mic;
+        mic.id = "mic";
+        mic.device = micInDevice.ext.get<AudioPortExt::Tag::device>().device;
+        mic.group = 0;
+        mic.indexInTheGroup = 0;
+        c.microphones = std::vector<MicrophoneInfo>{mic};
+
         return c;
     }();
-    return configuration;
+    return std::make_unique<Configuration>(configuration);
+}
+
+// Remote Submix configuration:
+//
+// Device ports:
+//  * "Remote Submix Out", OUT_SUBMIX
+//    - profile PCM 24-bit; STEREO; 48000
+//  * "Remote Submix In", IN_SUBMIX
+//    - profile PCM 24-bit; STEREO; 48000
+//
+// Mix ports:
+//  * "r_submix output", stream count unlimited
+//    - profile PCM 24-bit; STEREO; 48000
+//  * "r_submix input", stream count unlimited
+//    - profile PCM 24-bit; STEREO; 48000
+//
+// Routes:
+//  "r_submix output" -> "Remote Submix Out"
+//  "Remote Submix In" -> "r_submix input"
+//
+std::unique_ptr<Configuration> getRSubmixConfiguration() {
+    static const Configuration configuration = []() {
+        Configuration c;
+
+        // Device ports
+
+        AudioPort rsubmixOutDevice = createPort(c.nextPortId++, "Remote Submix Out", 0, false,
+                                                createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0));
+        rsubmixOutDevice.profiles.push_back(
+                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+        c.ports.push_back(rsubmixOutDevice);
+
+        AudioPort rsubmixInDevice = createPort(c.nextPortId++, "Remote Submix In", 0, true,
+                                               createDeviceExt(AudioDeviceType::IN_SUBMIX, 0));
+        rsubmixInDevice.profiles.push_back(
+                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+        c.ports.push_back(rsubmixInDevice);
+
+        // Mix ports
+
+        AudioPort rsubmixOutMix =
+                createPort(c.nextPortId++, "r_submix output", 0, false, createPortMixExt(0, 0));
+        rsubmixOutMix.profiles.push_back(
+                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+        c.ports.push_back(rsubmixOutMix);
+
+        AudioPort rsubmixInMix =
+                createPort(c.nextPortId++, "r_submix input", 0, true, createPortMixExt(0, 0));
+        rsubmixInMix.profiles.push_back(
+                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+        c.ports.push_back(rsubmixInMix);
+
+        c.routes.push_back(createRoute({rsubmixOutMix}, rsubmixOutDevice));
+        c.routes.push_back(createRoute({rsubmixInDevice}, rsubmixInMix));
+
+        return c;
+    }();
+    return std::make_unique<Configuration>(configuration);
 }
 
 }  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
index 74ed780..7ae9a66 100644
--- a/audio/aidl/default/EffectFactory.cpp
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+#include <iterator>
+#include <memory>
+#include <tuple>
+#include "include/effect-impl/EffectTypes.h"
 #define LOG_TAG "AHAL_EffectFactory"
 #include <dlfcn.h>
 #include <unordered_set>
@@ -51,15 +55,29 @@
 ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type_uuid,
                                          const std::optional<AudioUuid>& in_impl_uuid,
                                          const std::optional<AudioUuid>& in_proxy_uuid,
-                                         std::vector<Descriptor::Identity>* _aidl_return) {
-    std::copy_if(
-            mIdentitySet.begin(), mIdentitySet.end(), std::back_inserter(*_aidl_return),
-            [&](auto& desc) {
-                return (!in_type_uuid.has_value() || in_type_uuid.value() == desc.type) &&
-                       (!in_impl_uuid.has_value() || in_impl_uuid.value() == desc.uuid) &&
-                       (!in_proxy_uuid.has_value() ||
-                        (desc.proxy.has_value() && in_proxy_uuid.value() == desc.proxy.value()));
-            });
+                                         std::vector<Descriptor>* _aidl_return) {
+    // get the matching list
+    std::vector<Descriptor::Identity> idList;
+    std::copy_if(mIdentitySet.begin(), mIdentitySet.end(), std::back_inserter(idList),
+                 [&](auto& id) {
+                     return (!in_type_uuid.has_value() || in_type_uuid.value() == id.type) &&
+                            (!in_impl_uuid.has_value() || in_impl_uuid.value() == id.uuid) &&
+                            (!in_proxy_uuid.has_value() ||
+                             (id.proxy.has_value() && in_proxy_uuid.value() == id.proxy.value()));
+                 });
+    // query through the matching list
+    for (const auto& id : idList) {
+        if (mEffectLibMap.count(id.uuid)) {
+            Descriptor desc;
+            auto& entry = mEffectLibMap[id.uuid];
+            getDlSyms(entry);
+            auto& libInterface = std::get<kMapEntryInterfaceIndex>(entry);
+            RETURN_IF(!libInterface || !libInterface->queryEffectFunc, EX_NULL_POINTER,
+                      "dlNullQueryEffectFunc");
+            RETURN_IF_BINDER_EXCEPTION(libInterface->queryEffectFunc(&id.uuid, &desc));
+            _aidl_return->emplace_back(std::move(desc));
+        }
+    }
     return ndk::ScopedAStatus::ok();
 }
 
@@ -74,37 +92,16 @@
     return ndk::ScopedAStatus::ok();
 }
 
-#define RETURN_IF_BINDER_EXCEPTION(functor)                                 \
-    {                                                                       \
-        binder_exception_t exception = functor;                             \
-        if (EX_NONE != exception) {                                         \
-            LOG(ERROR) << #functor << ":  failed with error " << exception; \
-            return ndk::ScopedAStatus::fromExceptionCode(exception);        \
-        }                                                                   \
-    }
-
 ndk::ScopedAStatus Factory::createEffect(const AudioUuid& in_impl_uuid,
                                          std::shared_ptr<IEffect>* _aidl_return) {
     LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString();
     if (mEffectLibMap.count(in_impl_uuid)) {
-        auto& lib = mEffectLibMap[in_impl_uuid];
-        // didn't do dlsym yet
-        if (nullptr == lib.second) {
-            void* libHandle = lib.first.get();
-            auto dlInterface = std::make_unique<struct effect_dl_interface_s>();
-            dlInterface->createEffectFunc = (EffectCreateFunctor)dlsym(libHandle, "createEffect");
-            dlInterface->destroyEffectFunc =
-                    (EffectDestroyFunctor)dlsym(libHandle, "destroyEffect");
-            if (!dlInterface->createEffectFunc || !dlInterface->destroyEffectFunc) {
-                LOG(ERROR) << __func__
-                           << ": create or destroy symbol not exist in library: " << libHandle
-                           << " with dlerror: " << dlerror();
-                return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
-            }
-            lib.second = std::move(dlInterface);
-        }
+        auto& entry = mEffectLibMap[in_impl_uuid];
+        getDlSyms(entry);
 
-        auto& libInterface = lib.second;
+        auto& libInterface = std::get<kMapEntryInterfaceIndex>(entry);
+        RETURN_IF(!libInterface || !libInterface->createEffectFunc, EX_NULL_POINTER,
+                  "dlNullcreateEffectFunc");
         std::shared_ptr<IEffect> effectSp;
         RETURN_IF_BINDER_EXCEPTION(libInterface->createEffectFunc(&in_impl_uuid, &effectSp));
         if (!effectSp) {
@@ -131,9 +128,10 @@
         auto& uuid = uuidIt->second;
         // find implementation library with UUID
         if (auto libIt = mEffectLibMap.find(uuid); libIt != mEffectLibMap.end()) {
-            if (libIt->second.second->destroyEffectFunc) {
-                RETURN_IF_BINDER_EXCEPTION(libIt->second.second->destroyEffectFunc(in_handle));
-            }
+            auto& interface = std::get<kMapEntryInterfaceIndex>(libIt->second);
+            RETURN_IF(!interface || !interface->destroyEffectFunc, EX_NULL_POINTER,
+                      "dlNulldestroyEffectFunc");
+            RETURN_IF_BINDER_EXCEPTION(interface->destroyEffectFunc(in_handle));
         } else {
             LOG(ERROR) << __func__ << ": UUID " << uuid.toString() << " does not exist in libMap!";
             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
@@ -179,9 +177,13 @@
         return;
     }
 
-    LOG(DEBUG) << __func__ << " dlopen lib:" << libName << "\nimpl:" << impl.toString()
-               << "\nhandle:" << libHandle;
-    mEffectLibMap.insert({impl, std::make_pair(std::move(libHandle), nullptr)});
+    LOG(INFO) << __func__ << " dlopen lib:" << libName << "\nimpl:" << impl.toString()
+              << "\nhandle:" << libHandle;
+    auto interface = new effect_dl_interface_s{nullptr, nullptr, nullptr};
+    mEffectLibMap.insert(
+            {impl,
+             std::make_tuple(std::move(libHandle),
+                             std::unique_ptr<struct effect_dl_interface_s>(interface), libName)});
 }
 
 void Factory::createIdentityWithConfig(const EffectConfig::LibraryUuid& configLib,
@@ -226,4 +228,32 @@
     }
 }
 
+void Factory::getDlSyms(DlEntry& entry) {
+    auto& dlHandle = std::get<kMapEntryHandleIndex>(entry);
+    RETURN_VALUE_IF(!dlHandle, void(), "dlNullHandle");
+    // Get the reference of the DL interfaces in library map tuple.
+    auto& dlInterface = std::get<kMapEntryInterfaceIndex>(entry);
+    // return if interface already exist
+    if (!dlInterface->createEffectFunc) {
+        dlInterface->createEffectFunc = (EffectCreateFunctor)dlsym(dlHandle.get(), "createEffect");
+    }
+    if (!dlInterface->queryEffectFunc) {
+        dlInterface->queryEffectFunc = (EffectQueryFunctor)dlsym(dlHandle.get(), "queryEffect");
+    }
+    if (!dlInterface->destroyEffectFunc) {
+        dlInterface->destroyEffectFunc =
+                (EffectDestroyFunctor)dlsym(dlHandle.get(), "destroyEffect");
+    }
+
+    if (!dlInterface->createEffectFunc || !dlInterface->destroyEffectFunc ||
+        !dlInterface->queryEffectFunc) {
+        LOG(ERROR) << __func__ << ": create (" << dlInterface->createEffectFunc << "), query ("
+                   << dlInterface->queryEffectFunc << "), or destroy ("
+                   << dlInterface->destroyEffectFunc
+                   << ") not exist in library: " << std::get<kMapEntryLibNameIndex>(entry)
+                   << " handle: " << dlHandle << " with dlerror: " << dlerror();
+        return;
+    }
+}
+
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/EffectImpl.cpp b/audio/aidl/default/EffectImpl.cpp
index 2754bb6..139f262 100644
--- a/audio/aidl/default/EffectImpl.cpp
+++ b/audio/aidl/default/EffectImpl.cpp
@@ -19,47 +19,54 @@
 #include "effect-impl/EffectTypes.h"
 #include "include/effect-impl/EffectTypes.h"
 
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+
+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) {
+        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+                   << " in state: " << toString(state) << ", status: " << status.getDescription();
+        return EX_ILLEGAL_STATE;
+    }
+    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+    return EX_NONE;
+}
+
 namespace aidl::android::hardware::audio::effect {
 
 ndk::ScopedAStatus EffectImpl::open(const Parameter::Common& common,
                                     const std::optional<Parameter::Specific>& specific,
                                     OpenEffectReturn* ret) {
     LOG(DEBUG) << __func__;
-    {
-        std::lock_guard lg(mMutex);
-        RETURN_OK_IF(mState != State::INIT);
-        mContext = createContext(common);
-        RETURN_IF(!mContext, EX_ILLEGAL_ARGUMENT, "createContextFailed");
-        setContext(mContext);
-    }
+    RETURN_OK_IF(mState != State::INIT);
+    auto context = createContext(common);
+    RETURN_IF(!context, EX_NULL_POINTER, "createContextFailed");
 
     RETURN_IF_ASTATUS_NOT_OK(setParameterCommon(common), "setCommParamErr");
     if (specific.has_value()) {
         RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(specific.value()), "setSpecParamErr");
     }
 
-    RETURN_IF(createThread(LOG_TAG) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
+    mState = State::IDLE;
+    context->dupeFmq(ret);
+    RETURN_IF(createThread(context, getEffectName()) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
               "FailedToCreateWorker");
-
-    {
-        std::lock_guard lg(mMutex);
-        mContext->dupeFmq(ret);
-        mState = State::IDLE;
-    }
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus EffectImpl::close() {
-    std::lock_guard lg(mMutex);
     RETURN_OK_IF(mState == State::INIT);
     RETURN_IF(mState == State::PROCESSING, EX_ILLEGAL_STATE, "closeAtProcessing");
 
     // stop the worker thread, ignore the return code
     RETURN_IF(destroyThread() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
               "FailedToDestroyWorker");
+    mState = State::INIT;
     RETURN_IF(releaseContext() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
               "FailedToCreateWorker");
-    mState = State::INIT;
+
     LOG(DEBUG) << __func__;
     return ndk::ScopedAStatus::ok();
 }
@@ -113,29 +120,30 @@
 }
 
 ndk::ScopedAStatus EffectImpl::setParameterCommon(const Parameter& param) {
-    std::lock_guard lg(mMutex);
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    auto context = getContext();
+    RETURN_IF(!context, EX_NULL_POINTER, "nullContext");
+
     auto tag = param.getTag();
     switch (tag) {
         case Parameter::common:
-            RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
+            RETURN_IF(context->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
                       EX_ILLEGAL_ARGUMENT, "setCommFailed");
             break;
         case Parameter::deviceDescription:
-            RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
+            RETURN_IF(context->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
                               RetCode::SUCCESS,
                       EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
             break;
         case Parameter::mode:
-            RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
+            RETURN_IF(context->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
                       EX_ILLEGAL_ARGUMENT, "setModeFailed");
             break;
         case Parameter::source:
-            RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
+            RETURN_IF(context->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
                       EX_ILLEGAL_ARGUMENT, "setSourceFailed");
             break;
         case Parameter::volumeStereo:
-            RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
+            RETURN_IF(context->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
                               RetCode::SUCCESS,
                       EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed");
             break;
@@ -149,27 +157,28 @@
 }
 
 ndk::ScopedAStatus EffectImpl::getParameterCommon(const Parameter::Tag& tag, Parameter* param) {
-    std::lock_guard lg(mMutex);
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    auto context = getContext();
+    RETURN_IF(!context, EX_NULL_POINTER, "nullContext");
+
     switch (tag) {
         case Parameter::common: {
-            param->set<Parameter::common>(mContext->getCommon());
+            param->set<Parameter::common>(context->getCommon());
             break;
         }
         case Parameter::deviceDescription: {
-            param->set<Parameter::deviceDescription>(mContext->getOutputDevice());
+            param->set<Parameter::deviceDescription>(context->getOutputDevice());
             break;
         }
         case Parameter::mode: {
-            param->set<Parameter::mode>(mContext->getAudioMode());
+            param->set<Parameter::mode>(context->getAudioMode());
             break;
         }
         case Parameter::source: {
-            param->set<Parameter::source>(mContext->getAudioSource());
+            param->set<Parameter::source>(context->getAudioSource());
             break;
         }
         case Parameter::volumeStereo: {
-            param->set<Parameter::volumeStereo>(mContext->getVolumeStereo());
+            param->set<Parameter::volumeStereo>(context->getVolumeStereo());
             break;
         }
         default: {
@@ -182,39 +191,30 @@
 }
 
 ndk::ScopedAStatus EffectImpl::getState(State* state) {
-    std::lock_guard lg(mMutex);
     *state = mState;
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus EffectImpl::command(CommandId command) {
-    std::lock_guard lg(mMutex);
+    RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "CommandStateError");
     LOG(DEBUG) << __func__ << ": receive command: " << toString(command) << " at state "
                << toString(mState);
-    RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "CommandStateError");
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     switch (command) {
         case CommandId::START:
             RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "instanceNotOpen");
             RETURN_OK_IF(mState == State::PROCESSING);
-            RETURN_IF_ASTATUS_NOT_OK(commandStart(), "commandStartFailed");
-            mState = State::PROCESSING;
+            RETURN_IF_ASTATUS_NOT_OK(commandImpl(command), "commandImplFailed");
             startThread();
-            return ndk::ScopedAStatus::ok();
+            mState = State::PROCESSING;
+            break;
         case CommandId::STOP:
-            RETURN_OK_IF(mState == State::IDLE);
-            mState = State::IDLE;
-            RETURN_IF_ASTATUS_NOT_OK(commandStop(), "commandStopFailed");
-            stopThread();
-            return ndk::ScopedAStatus::ok();
         case CommandId::RESET:
             RETURN_OK_IF(mState == State::IDLE);
-            mState = State::IDLE;
-            RETURN_IF_ASTATUS_NOT_OK(commandStop(), "commandStopFailed");
             stopThread();
-            mContext->resetBuffer();
-            return ndk::ScopedAStatus::ok();
+            RETURN_IF_ASTATUS_NOT_OK(commandImpl(command), "commandImplFailed");
+            mState = State::IDLE;
+            break;
         default:
             LOG(ERROR) << __func__ << " instance still processing";
             return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
@@ -224,6 +224,15 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus EffectImpl::commandImpl(CommandId command) {
+    auto context = getContext();
+    RETURN_IF(!context, EX_NULL_POINTER, "nullContext");
+    if (command == CommandId::RESET) {
+        context->resetBuffer();
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
 void EffectImpl::cleanUp() {
     command(CommandId::STOP);
     close();
@@ -238,19 +247,12 @@
 }
 
 // A placeholder processing implementation to copy samples from input to output
-IEffect::Status EffectImpl::effectProcessImpl(float* in, float* out, int processSamples) {
-    // lock before access context/parameters
-    std::lock_guard lg(mMutex);
-    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
-    RETURN_VALUE_IF(!mContext, status, "nullContext");
-    auto frameSize = mContext->getInputFrameSize();
-    RETURN_VALUE_IF(0 == frameSize, status, "frameSizeIs0");
-    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << processSamples
-               << " frames " << processSamples * sizeof(float) / frameSize;
-    for (int i = 0; i < processSamples; i++) {
+IEffect::Status EffectImpl::effectProcessImpl(float* in, float* out, int samples) {
+    for (int i = 0; i < samples; i++) {
         *out++ = *in++;
     }
-    LOG(DEBUG) << __func__ << " done processing " << processSamples << " samples";
-    return {STATUS_OK, processSamples, processSamples};
+    LOG(DEBUG) << __func__ << " done processing " << samples << " samples";
+    return {STATUS_OK, samples, samples};
 }
+
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/EffectThread.cpp b/audio/aidl/default/EffectThread.cpp
index 80f120b..2b3513d 100644
--- a/audio/aidl/default/EffectThread.cpp
+++ b/audio/aidl/default/EffectThread.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <memory>
 #define LOG_TAG "AHAL_EffectThread"
 #include <android-base/logging.h>
 #include <pthread.h>
@@ -32,13 +33,18 @@
     LOG(DEBUG) << __func__ << " done";
 };
 
-RetCode EffectThread::createThread(const std::string& name, const int priority) {
+RetCode EffectThread::createThread(std::shared_ptr<EffectContext> context, const std::string& name,
+                                   const int priority) {
     if (mThread.joinable()) {
         LOG(WARNING) << __func__ << " thread already created, no-op";
         return RetCode::SUCCESS;
     }
     mName = name;
     mPriority = priority;
+    {
+        std::lock_guard lg(mThreadMutex);
+        mThreadContext = std::move(context);
+    }
     mThread = std::thread(&EffectThread::threadLoop, this);
     LOG(DEBUG) << __func__ << " " << name << " priority " << mPriority << " done";
     return RetCode::SUCCESS;
@@ -46,7 +52,7 @@
 
 RetCode EffectThread::destroyThread() {
     {
-        std::lock_guard lg(mMutex);
+        std::lock_guard lg(mThreadMutex);
         mStop = mExit = true;
     }
     mCv.notify_one();
@@ -54,6 +60,11 @@
     if (mThread.joinable()) {
         mThread.join();
     }
+
+    {
+        std::lock_guard lg(mThreadMutex);
+        mThreadContext.reset();
+    }
     LOG(DEBUG) << __func__ << " done";
     return RetCode::SUCCESS;
 }
@@ -65,7 +76,7 @@
     }
 
     {
-        std::lock_guard lg(mMutex);
+        std::lock_guard lg(mThreadMutex);
         if (!mStop) {
             LOG(WARNING) << __func__ << " already start";
             return RetCode::SUCCESS;
@@ -85,7 +96,7 @@
     }
 
     {
-        std::lock_guard lg(mMutex);
+        std::lock_guard lg(mThreadMutex);
         if (mStop) {
             LOG(WARNING) << __func__ << " already stop";
             return RetCode::SUCCESS;
@@ -97,13 +108,13 @@
 }
 
 void EffectThread::threadLoop() {
-    pthread_setname_np(pthread_self(), mName.substr(0, MAX_TASK_COMM_LEN - 1).c_str());
+    pthread_setname_np(pthread_self(), mName.substr(0, kMaxTaskNameLen - 1).c_str());
     setpriority(PRIO_PROCESS, 0, mPriority);
     while (true) {
         bool needExit = false;
         {
-            std::unique_lock l(mMutex);
-            mCv.wait(l, [&]() REQUIRES(mMutex) {
+            std::unique_lock l(mThreadMutex);
+            mCv.wait(l, [&]() REQUIRES(mThreadMutex) {
                 needExit = mExit;
                 return mExit || !mStop;
             });
@@ -112,9 +123,41 @@
             LOG(WARNING) << __func__ << " EXIT!";
             return;
         }
-        // process without lock
+
         process();
     }
 }
 
+void EffectThread::process() {
+    std::shared_ptr<EffectContext> context;
+    {
+        std::lock_guard lg(mThreadMutex);
+        context = mThreadContext;
+        RETURN_VALUE_IF(!context, void(), "nullContext");
+    }
+    std::shared_ptr<EffectContext::StatusMQ> statusMQ = context->getStatusFmq();
+    std::shared_ptr<EffectContext::DataMQ> inputMQ = context->getInputDataFmq();
+    std::shared_ptr<EffectContext::DataMQ> outputMQ = context->getOutputDataFmq();
+    auto buffer = context->getWorkBuffer();
+
+    // Only this worker will read from input data MQ and write to output data MQ.
+    auto readSamples = inputMQ->availableToRead(), writeSamples = outputMQ->availableToWrite();
+    if (readSamples && writeSamples) {
+        auto processSamples = std::min(readSamples, writeSamples);
+        LOG(DEBUG) << __func__ << " available to read " << readSamples << " available to write "
+                   << writeSamples << " process " << processSamples;
+
+        inputMQ->read(buffer, processSamples);
+
+        // call effectProcessImpl without lock
+        IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples);
+        outputMQ->write(buffer, status.fmqProduced);
+        statusMQ->writeBlocking(&status, 1);
+        LOG(DEBUG) << __func__ << " done processing, effect consumed " << status.fmqConsumed
+                   << " produced " << status.fmqProduced;
+    } else {
+        // TODO: maybe add some sleep here to avoid busy waiting
+    }
+}
+
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/EngineConfigXmlConverter.cpp b/audio/aidl/default/EngineConfigXmlConverter.cpp
new file mode 100644
index 0000000..71b4b0e
--- /dev/null
+++ b/audio/aidl/default/EngineConfigXmlConverter.cpp
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <functional>
+#include <unordered_map>
+
+#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
+
+#include "core-impl/EngineConfigXmlConverter.h"
+
+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::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::AudioProductStrategyType;
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::AudioStreamType;
+using aidl::android::media::audio::common::AudioUsage;
+
+namespace xsd = android::audio::policy::engine::configuration;
+
+namespace aidl::android::hardware::audio::core::internal {
+
+/**
+ * Valid curve points take the form "<index>,<attenuationMb>", where the index
+ * must be in the range [0,100]. kInvalidCurvePointIndex is used to indicate
+ * that a point was formatted incorrectly (e.g. if a vendor accidentally typed a
+ * '.' instead of a ',' in their XML)-- using such a curve point will result in
+ * failed VTS tests.
+ */
+static const int8_t kInvalidCurvePointIndex = -1;
+
+void EngineConfigXmlConverter::initProductStrategyMap() {
+#define STRATEGY_ENTRY(name) {"STRATEGY_" #name, static_cast<int>(AudioProductStrategyType::name)}
+
+    mProductStrategyMap = {STRATEGY_ENTRY(MEDIA),
+                           STRATEGY_ENTRY(PHONE),
+                           STRATEGY_ENTRY(SONIFICATION),
+                           STRATEGY_ENTRY(SONIFICATION_RESPECTFUL),
+                           STRATEGY_ENTRY(DTMF),
+                           STRATEGY_ENTRY(ENFORCED_AUDIBLE),
+                           STRATEGY_ENTRY(TRANSMITTED_THROUGH_SPEAKER),
+                           STRATEGY_ENTRY(ACCESSIBILITY)};
+#undef STRATEGY_ENTRY
+}
+
+int EngineConfigXmlConverter::convertProductStrategyNameToAidl(
+        const std::string& xsdcProductStrategyName) {
+    const auto [it, success] = mProductStrategyMap.insert(
+            std::make_pair(xsdcProductStrategyName, mNextVendorStrategy));
+    if (success) {
+        mNextVendorStrategy++;
+    }
+    return it->second;
+}
+
+bool isDefaultAudioAttributes(const AudioAttributes& attributes) {
+    return ((attributes.contentType == AudioContentType::UNKNOWN) &&
+            (attributes.usage == AudioUsage::UNKNOWN) &&
+            (attributes.source == AudioSource::DEFAULT) && (attributes.flags == 0) &&
+            (attributes.tags.empty()));
+}
+
+AudioAttributes EngineConfigXmlConverter::convertAudioAttributesToAidl(
+        const xsd::AttributesType& xsdcAudioAttributes) {
+    if (xsdcAudioAttributes.hasAttributesRef()) {
+        if (mAttributesReferenceMap.empty()) {
+            mAttributesReferenceMap =
+                    generateReferenceMap<xsd::AttributesRef, xsd::AttributesRefType>(
+                            getXsdcConfig()->getAttributesRef());
+        }
+        return convertAudioAttributesToAidl(
+                *(mAttributesReferenceMap.at(xsdcAudioAttributes.getAttributesRef())
+                          .getFirstAttributes()));
+    }
+    AudioAttributes aidlAudioAttributes;
+    if (xsdcAudioAttributes.hasContentType()) {
+        aidlAudioAttributes.contentType = static_cast<AudioContentType>(
+                xsdcAudioAttributes.getFirstContentType()->getValue());
+    }
+    if (xsdcAudioAttributes.hasUsage()) {
+        aidlAudioAttributes.usage =
+                static_cast<AudioUsage>(xsdcAudioAttributes.getFirstUsage()->getValue());
+    }
+    if (xsdcAudioAttributes.hasSource()) {
+        aidlAudioAttributes.source =
+                static_cast<AudioSource>(xsdcAudioAttributes.getFirstSource()->getValue());
+    }
+    if (xsdcAudioAttributes.hasFlags()) {
+        std::vector<xsd::FlagType> xsdcFlagTypeVec =
+                xsdcAudioAttributes.getFirstFlags()->getValue();
+        for (const xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) {
+            if (xsdcFlagType != xsd::FlagType::AUDIO_FLAG_NONE) {
+                aidlAudioAttributes.flags |= 1 << (static_cast<int>(xsdcFlagType) - 1);
+            }
+        }
+    }
+    if (xsdcAudioAttributes.hasBundle()) {
+        const xsd::BundleType* xsdcBundle = xsdcAudioAttributes.getFirstBundle();
+        aidlAudioAttributes.tags[0] = xsdcBundle->getKey() + "=" + xsdcBundle->getValue();
+    }
+    if (isDefaultAudioAttributes(aidlAudioAttributes)) {
+        mDefaultProductStrategyId = std::optional<int>{-1};
+    }
+    return aidlAudioAttributes;
+}
+
+AudioHalAttributesGroup EngineConfigXmlConverter::convertAttributesGroupToAidl(
+        const xsd::AttributesGroup& xsdcAttributesGroup) {
+    AudioHalAttributesGroup aidlAttributesGroup;
+    static const int kStreamTypeEnumOffset =
+            static_cast<int>(xsd::Stream::AUDIO_STREAM_VOICE_CALL) -
+            static_cast<int>(AudioStreamType::VOICE_CALL);
+    aidlAttributesGroup.streamType = static_cast<AudioStreamType>(
+            static_cast<int>(xsdcAttributesGroup.getStreamType()) - kStreamTypeEnumOffset);
+    aidlAttributesGroup.volumeGroupName = xsdcAttributesGroup.getVolumeGroup();
+    if (xsdcAttributesGroup.hasAttributes_optional()) {
+        aidlAttributesGroup.attributes =
+                convertCollectionToAidl<xsd::AttributesType, AudioAttributes>(
+                        xsdcAttributesGroup.getAttributes_optional(),
+                        std::bind(&EngineConfigXmlConverter::convertAudioAttributesToAidl, this,
+                                  std::placeholders::_1));
+    } else if (xsdcAttributesGroup.hasContentType_optional() ||
+               xsdcAttributesGroup.hasUsage_optional() ||
+               xsdcAttributesGroup.hasSource_optional() ||
+               xsdcAttributesGroup.hasFlags_optional() ||
+               xsdcAttributesGroup.hasBundle_optional()) {
+        aidlAttributesGroup.attributes.push_back(convertAudioAttributesToAidl(xsd::AttributesType(
+                xsdcAttributesGroup.getContentType_optional(),
+                xsdcAttributesGroup.getUsage_optional(), xsdcAttributesGroup.getSource_optional(),
+                xsdcAttributesGroup.getFlags_optional(), xsdcAttributesGroup.getBundle_optional(),
+                std::nullopt)));
+
+    } else {
+        // do nothing;
+        // TODO: check if this is valid or if we should treat as an error.
+        // Currently, attributes are not mandatory in schema, but an AttributesGroup
+        // without attributes does not make much sense.
+    }
+    return aidlAttributesGroup;
+}
+
+AudioHalProductStrategy EngineConfigXmlConverter::convertProductStrategyToAidl(
+        const xsd::ProductStrategies::ProductStrategy& xsdcProductStrategy) {
+    AudioHalProductStrategy aidlProductStrategy;
+
+    aidlProductStrategy.id = convertProductStrategyNameToAidl(xsdcProductStrategy.getName());
+
+    if (xsdcProductStrategy.hasAttributesGroup()) {
+        aidlProductStrategy.attributesGroups =
+                convertCollectionToAidl<xsd::AttributesGroup, AudioHalAttributesGroup>(
+                        xsdcProductStrategy.getAttributesGroup(),
+                        std::bind(&EngineConfigXmlConverter::convertAttributesGroupToAidl, this,
+                                  std::placeholders::_1));
+    }
+    if ((mDefaultProductStrategyId != std::nullopt) && (mDefaultProductStrategyId.value() == -1)) {
+        mDefaultProductStrategyId = aidlProductStrategy.id;
+    }
+    return aidlProductStrategy;
+}
+
+AudioHalVolumeCurve::CurvePoint EngineConfigXmlConverter::convertCurvePointToAidl(
+        const std::string& xsdcCurvePoint) {
+    AudioHalVolumeCurve::CurvePoint aidlCurvePoint{};
+    if (sscanf(xsdcCurvePoint.c_str(), "%" SCNd8 ",%d", &aidlCurvePoint.index,
+               &aidlCurvePoint.attenuationMb) != 2) {
+        aidlCurvePoint.index = kInvalidCurvePointIndex;
+    }
+    return aidlCurvePoint;
+}
+
+AudioHalVolumeCurve EngineConfigXmlConverter::convertVolumeCurveToAidl(
+        const xsd::Volume& xsdcVolumeCurve) {
+    AudioHalVolumeCurve aidlVolumeCurve;
+    aidlVolumeCurve.deviceCategory =
+            static_cast<AudioHalVolumeCurve::DeviceCategory>(xsdcVolumeCurve.getDeviceCategory());
+    if (xsdcVolumeCurve.hasRef()) {
+        if (mVolumesReferenceMap.empty()) {
+            mVolumesReferenceMap = generateReferenceMap<xsd::VolumesType, xsd::VolumeRef>(
+                    getXsdcConfig()->getVolumes());
+        }
+        aidlVolumeCurve.curvePoints =
+                convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+                        mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
+                        std::bind(&EngineConfigXmlConverter::convertCurvePointToAidl, this,
+                                  std::placeholders::_1));
+    } else {
+        aidlVolumeCurve.curvePoints =
+                convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
+                        xsdcVolumeCurve.getPoint(),
+                        std::bind(&EngineConfigXmlConverter::convertCurvePointToAidl, this,
+                                  std::placeholders::_1));
+    }
+    return aidlVolumeCurve;
+}
+
+AudioHalVolumeGroup EngineConfigXmlConverter::convertVolumeGroupToAidl(
+        const xsd::VolumeGroupsType::VolumeGroup& xsdcVolumeGroup) {
+    AudioHalVolumeGroup aidlVolumeGroup;
+    aidlVolumeGroup.name = xsdcVolumeGroup.getName();
+    aidlVolumeGroup.minIndex = xsdcVolumeGroup.getIndexMin();
+    aidlVolumeGroup.maxIndex = xsdcVolumeGroup.getIndexMax();
+    aidlVolumeGroup.volumeCurves = convertCollectionToAidl<xsd::Volume, AudioHalVolumeCurve>(
+            xsdcVolumeGroup.getVolume(),
+            std::bind(&EngineConfigXmlConverter::convertVolumeCurveToAidl, this,
+                      std::placeholders::_1));
+    return aidlVolumeGroup;
+}
+
+AudioHalCapCriterion EngineConfigXmlConverter::convertCapCriterionToAidl(
+        const xsd::CriterionType& xsdcCriterion) {
+    AudioHalCapCriterion aidlCapCriterion;
+    aidlCapCriterion.name = xsdcCriterion.getName();
+    aidlCapCriterion.criterionTypeName = xsdcCriterion.getType();
+    aidlCapCriterion.defaultLiteralValue = xsdcCriterion.get_default();
+    return aidlCapCriterion;
+}
+
+std::string EngineConfigXmlConverter::convertCriterionTypeValueToAidl(
+        const xsd::ValueType& xsdcCriterionTypeValue) {
+    return xsdcCriterionTypeValue.getLiteral();
+}
+
+AudioHalCapCriterionType EngineConfigXmlConverter::convertCapCriterionTypeToAidl(
+        const xsd::CriterionTypeType& xsdcCriterionType) {
+    AudioHalCapCriterionType aidlCapCriterionType;
+    aidlCapCriterionType.name = xsdcCriterionType.getName();
+    aidlCapCriterionType.isInclusive = !(static_cast<bool>(xsdcCriterionType.getType()));
+    aidlCapCriterionType.values =
+            convertWrappedCollectionToAidl<xsd::ValuesType, xsd::ValueType, std::string>(
+                    xsdcCriterionType.getValues(), &xsd::ValuesType::getValue,
+                    std::bind(&EngineConfigXmlConverter::convertCriterionTypeValueToAidl, this,
+                              std::placeholders::_1));
+    return aidlCapCriterionType;
+}
+
+AudioHalEngineConfig& EngineConfigXmlConverter::getAidlEngineConfig() {
+    return mAidlEngineConfig;
+}
+
+void EngineConfigXmlConverter::init() {
+    initProductStrategyMap();
+    if (getXsdcConfig()->hasProductStrategies()) {
+        mAidlEngineConfig.productStrategies =
+                convertWrappedCollectionToAidl<xsd::ProductStrategies,
+                                               xsd::ProductStrategies::ProductStrategy,
+                                               AudioHalProductStrategy>(
+                        getXsdcConfig()->getProductStrategies(),
+                        &xsd::ProductStrategies::getProductStrategy,
+                        std::bind(&EngineConfigXmlConverter::convertProductStrategyToAidl, this,
+                                  std::placeholders::_1));
+        if (mDefaultProductStrategyId) {
+            mAidlEngineConfig.defaultProductStrategyId = mDefaultProductStrategyId.value();
+        }
+    }
+    if (getXsdcConfig()->hasVolumeGroups()) {
+        mAidlEngineConfig.volumeGroups = convertWrappedCollectionToAidl<
+                xsd::VolumeGroupsType, xsd::VolumeGroupsType::VolumeGroup, AudioHalVolumeGroup>(
+                getXsdcConfig()->getVolumeGroups(), &xsd::VolumeGroupsType::getVolumeGroup,
+                std::bind(&EngineConfigXmlConverter::convertVolumeGroupToAidl, this,
+                          std::placeholders::_1));
+    }
+    if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) {
+        AudioHalEngineConfig::CapSpecificConfig capSpecificConfig;
+        capSpecificConfig.criteria =
+                convertWrappedCollectionToAidl<xsd::CriteriaType, xsd::CriterionType,
+                                               AudioHalCapCriterion>(
+                        getXsdcConfig()->getCriteria(), &xsd::CriteriaType::getCriterion,
+                        std::bind(&EngineConfigXmlConverter::convertCapCriterionToAidl, this,
+                                  std::placeholders::_1));
+        capSpecificConfig.criterionTypes =
+                convertWrappedCollectionToAidl<xsd::CriterionTypesType, xsd::CriterionTypeType,
+                                               AudioHalCapCriterionType>(
+                        getXsdcConfig()->getCriterion_types(),
+                        &xsd::CriterionTypesType::getCriterion_type,
+                        std::bind(&EngineConfigXmlConverter::convertCapCriterionTypeToAidl, this,
+                                  std::placeholders::_1));
+        mAidlEngineConfig.capSpecificConfig = capSpecificConfig;
+    }
+}
+}  // namespace aidl::android::hardware::audio::core::internal
\ No newline at end of file
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 971d946..47d6fa4 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -238,7 +238,14 @@
 
 internal::Configuration& Module::getConfig() {
     if (!mConfig) {
-        mConfig.reset(new internal::Configuration(internal::getNullPrimaryConfiguration()));
+        switch (mType) {
+            case Type::DEFAULT:
+                mConfig = std::move(internal::getPrimaryConfiguration());
+                break;
+            case Type::R_SUBMIX:
+                mConfig = std::move(internal::getRSubmixConfiguration());
+                break;
+        }
     }
     return *mConfig;
 }
diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.xml b/audio/aidl/default/android.hardware.audio.service-aidl.xml
index bb4b01a..46b665f 100644
--- a/audio/aidl/default/android.hardware.audio.service-aidl.xml
+++ b/audio/aidl/default/android.hardware.audio.service-aidl.xml
@@ -7,6 +7,11 @@
   <hal format="aidl">
     <name>android.hardware.audio.core</name>
     <version>1</version>
+    <fqname>IModule/r_submix</fqname>
+  </hal>
+  <hal format="aidl">
+    <name>android.hardware.audio.core</name>
+    <version>1</version>
     <fqname>IConfig/default</fqname>
   </hal>
 </manifest>
diff --git a/audio/aidl/default/bassboost/BassBoostSw.cpp b/audio/aidl/default/bassboost/BassBoostSw.cpp
index c52d16f..61976c8 100644
--- a/audio/aidl/default/bassboost/BassBoostSw.cpp
+++ b/audio/aidl/default/bassboost/BassBoostSw.cpp
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
+#include <algorithm>
 #include <cstddef>
+#include <memory>
 #define LOG_TAG "AHAL_BassBoostSw"
 #include <Utils.h>
-#include <algorithm>
 #include <unordered_set>
 
 #include <android-base/logging.h>
@@ -26,6 +27,7 @@
 #include "BassBoostSw.h"
 
 using aidl::android::hardware::audio::effect::BassBoostSw;
+using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::kBassBoostSwImplUUID;
 using aidl::android::hardware::audio::effect::State;
@@ -47,23 +49,31 @@
     }
 }
 
-extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
-    if (!instanceSp) {
-        return EX_NONE;
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kBassBoostSwImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
     }
-    State state;
-    ndk::ScopedAStatus status = instanceSp->getState(&state);
-    if (!status.isOk() || State::INIT != state) {
-        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
-                   << " in state: " << toString(state) << ", status: " << status.getDescription();
-        return EX_ILLEGAL_STATE;
-    }
-    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+    *_aidl_return = BassBoostSw::kDescriptor;
     return EX_NONE;
 }
 
 namespace aidl::android::hardware::audio::effect {
 
+const std::string BassBoostSw::kEffectName = "BassBoostSw";
+const bool BassBoostSw::kStrengthSupported = true;
+const BassBoost::Capability BassBoostSw::kCapability = {.strengthSupported = kStrengthSupported};
+const Descriptor BassBoostSw::kDescriptor = {
+        .common = {.id = {.type = kBassBoostTypeUUID,
+                          .uuid = kBassBoostSwImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = BassBoostSw::kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = Capability::make<Capability::bassBoost>(BassBoostSw::kCapability)};
+
 ndk::ScopedAStatus BassBoostSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
     *_aidl_return = kDescriptor;
@@ -73,28 +83,74 @@
 ndk::ScopedAStatus BassBoostSw::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::bassBoost != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
-    std::lock_guard lg(mMutex);
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
-    mSpecificParam = specific.get<Parameter::Specific::bassBoost>();
-    LOG(DEBUG) << __func__ << " success with: " << specific.toString();
-    return ndk::ScopedAStatus::ok();
+    auto& bbParam = specific.get<Parameter::Specific::bassBoost>();
+    auto tag = bbParam.getTag();
+
+    switch (tag) {
+        case BassBoost::strengthPm: {
+            RETURN_IF(!kStrengthSupported, EX_ILLEGAL_ARGUMENT, "SettingStrengthNotSupported");
+
+            RETURN_IF(mContext->setBbStrengthPm(bbParam.get<BassBoost::strengthPm>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "strengthPmNotSupported");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "BassBoostTagNotSupported");
+        }
+    }
 }
 
 ndk::ScopedAStatus BassBoostSw::getParameterSpecific(const Parameter::Id& id,
                                                      Parameter::Specific* specific) {
     auto tag = id.getTag();
     RETURN_IF(Parameter::Id::bassBoostTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
-    specific->set<Parameter::Specific::bassBoost>(mSpecificParam);
+    auto bbId = id.get<Parameter::Id::bassBoostTag>();
+    auto bbIdTag = bbId.getTag();
+    switch (bbIdTag) {
+        case BassBoost::Id::commonTag:
+            return getParameterBassBoost(bbId.get<BassBoost::Id::commonTag>(), specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "BassBoostTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus BassBoostSw::getParameterBassBoost(const BassBoost::Tag& tag,
+                                                      Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    BassBoost bbParam;
+    switch (tag) {
+        case BassBoost::strengthPm: {
+            bbParam.set<BassBoost::strengthPm>(mContext->getBbStrengthPm());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "BassBoostTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::bassBoost>(bbParam);
     return ndk::ScopedAStatus::ok();
 }
 
 std::shared_ptr<EffectContext> BassBoostSw::createContext(const Parameter::Common& common) {
     if (mContext) {
         LOG(DEBUG) << __func__ << " context already exist";
-        return mContext;
+    } else {
+        mContext = std::make_shared<BassBoostSwContext>(1 /* statusFmqDepth */, common);
     }
-    mContext = std::make_shared<BassBoostSwContext>(1 /* statusFmqDepth */, common);
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> BassBoostSw::getContext() {
     return mContext;
 }
 
@@ -106,13 +162,13 @@
 }
 
 // Processing method running in EffectWorker thread.
-IEffect::Status BassBoostSw::effectProcessImpl(float* in, float* out, int process) {
+IEffect::Status BassBoostSw::effectProcessImpl(float* in, float* out, int samples) {
     // TODO: get data buffer and process.
-    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
-    for (int i = 0; i < process; i++) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    for (int i = 0; i < samples; i++) {
         *out++ = *in++;
     }
-    return {STATUS_OK, process, process};
+    return {STATUS_OK, samples, samples};
 }
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/bassboost/BassBoostSw.h b/audio/aidl/default/bassboost/BassBoostSw.h
index 90a8887..411b9c9 100644
--- a/audio/aidl/default/bassboost/BassBoostSw.h
+++ b/audio/aidl/default/bassboost/BassBoostSw.h
@@ -32,11 +32,29 @@
         : EffectContext(statusDepth, common) {
         LOG(DEBUG) << __func__;
     }
-    // TODO: add specific context here
+
+    RetCode setBbStrengthPm(int strength) {
+        if (strength < BassBoost::MIN_PER_MILLE_STRENGTH ||
+            strength > BassBoost::MAX_PER_MILLE_STRENGTH) {
+            LOG(ERROR) << __func__ << " invalid strength: " << strength;
+            return RetCode::ERROR_ILLEGAL_PARAMETER;
+        }
+        // TODO : Add implementation to apply new strength
+        mStrength = strength;
+        return RetCode::SUCCESS;
+    }
+    int getBbStrengthPm() const { return mStrength; }
+
+  private:
+    int mStrength;
 };
 
 class BassBoostSw final : public EffectImpl {
   public:
+    static const std::string kEffectName;
+    static const bool kStrengthSupported;
+    static const BassBoost::Capability kCapability;
+    static const Descriptor kDescriptor;
     BassBoostSw() { LOG(DEBUG) << __func__; }
     ~BassBoostSw() {
         cleanUp();
@@ -47,27 +65,17 @@
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
     ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
                                             Parameter::Specific* specific) override;
-    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+
     std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
     RetCode releaseContext() override;
 
+    std::string getEffectName() override { return kEffectName; };
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+
   private:
     std::shared_ptr<BassBoostSwContext> mContext;
-    /* capabilities */
-    const BassBoost::Capability kCapability;
-    /* Effect descriptor */
-    const Descriptor kDescriptor = {
-            .common = {.id = {.type = kBassBoostTypeUUID,
-                              .uuid = kBassBoostSwImplUUID,
-                              .proxy = std::nullopt},
-                       .flags = {.type = Flags::Type::INSERT,
-                                 .insert = Flags::Insert::FIRST,
-                                 .volume = Flags::Volume::CTRL},
-                       .name = "BassBoostSw",
-                       .implementor = "The Android Open Source Project"},
-            .capability = Capability::make<Capability::bassBoost>(kCapability)};
-
-    /* parameters */
-    BassBoost mSpecificParam;
+    ndk::ScopedAStatus getParameterBassBoost(const BassBoost::Tag& tag,
+                                             Parameter::Specific* specific);
 };
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/config/audioPolicy/Android.bp b/audio/aidl/default/config/audioPolicy/Android.bp
new file mode 100644
index 0000000..6d8a148
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/Android.bp
@@ -0,0 +1,15 @@
+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"],
+}
+
+xsd_config {
+    name: "audio_policy_configuration_aidl_default",
+    srcs: ["audio_policy_configuration.xsd"],
+    package_name: "android.audio.policy.configuration",
+    nullability: true,
+}
diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt
new file mode 100644
index 0000000..c0ffe70
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/api/current.txt
@@ -0,0 +1,607 @@
+// Signature format: 2.0
+package android.audio.policy.configuration {
+
+  public class AttachedDevices {
+    ctor public AttachedDevices();
+    method @Nullable public java.util.List<java.lang.String> getItem();
+  }
+
+  public enum AudioChannelMask {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_1;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_10;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_11;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_12;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_13;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_14;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_15;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_16;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_17;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_18;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_19;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_2;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_20;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_21;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_22;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_23;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_24;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_3;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_4;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_5;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_6;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_7;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_8;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_9;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_2POINT0POINT2;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_2POINT1POINT2;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_3POINT0POINT2;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_3POINT1POINT2;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_5POINT1;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_6;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_FRONT_BACK;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_MONO;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_STEREO;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_CALL_MONO;
+    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_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;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT1POINT2;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_3POINT0POINT2;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_3POINT1;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_3POINT1POINT2;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1POINT2;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1POINT4;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1_BACK;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1_SIDE;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_6POINT1;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1POINT2;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1POINT4;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_9POINT1POINT4;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_9POINT1POINT6;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_HAPTIC_AB;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_MONO;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_MONO_HAPTIC_A;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_PENTA;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_QUAD;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_QUAD_BACK;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_QUAD_SIDE;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_STEREO;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_SURROUND;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_TRI;
+    enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_TRI_BACK;
+  }
+
+  public enum AudioContentType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_MOVIE;
+    enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_MUSIC;
+    enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_SONIFICATION;
+    enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_SPEECH;
+    enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_ULTRASOUND;
+    enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_UNKNOWN;
+  }
+
+  public enum AudioDevice {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_AMBIENT;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_AUX_DIGITAL;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_BACK_MIC;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_BLE_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_BLE;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_BUILTIN_MIC;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_BUS;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_COMMUNICATION;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_DEFAULT;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_ECHO_REFERENCE;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_FM_TUNER;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_HDMI;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_HDMI_ARC;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_HDMI_EARC;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_IP;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_LINE;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_LOOPBACK;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_PROXY;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_SPDIF;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_STUB;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_TELEPHONY_RX;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_TV_TUNER;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_USB_ACCESSORY;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_USB_DEVICE;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_USB_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_VOICE_CALL;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_WIRED_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_NONE;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_AUX_DIGITAL;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_AUX_LINE;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_BLE_BROADCAST;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_BLE_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_BLE_SPEAKER;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_BUS;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_DEFAULT;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_EARPIECE;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_ECHO_CANCELLER;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_FM;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_HDMI;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_HDMI_ARC;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_HDMI_EARC;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_HEARING_AID;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_IP;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_LINE;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_PROXY;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_SPDIF;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_SPEAKER;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_STUB;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_TELEPHONY_TX;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_USB_ACCESSORY;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_USB_DEVICE;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_USB_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+    enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADSET;
+  }
+
+  public enum AudioEncapsulationType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_IEC61937;
+    enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_NONE;
+  }
+
+  public enum AudioFormat {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADIF;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADTS;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADTS_ELD;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADTS_ERLC;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADTS_HE_V1;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADTS_HE_V2;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADTS_LC;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADTS_LD;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADTS_LTP;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADTS_MAIN;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADTS_SCALABLE;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADTS_SSR;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ADTS_XHE;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ELD;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_ERLC;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_HE_V1;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_HE_V2;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_LATM;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_LATM_HE_V1;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_LATM_HE_V2;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_LATM_LC;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_LC;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_LD;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_LTP;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_MAIN;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_SCALABLE;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_SSR;
+    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_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;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AMR_WB_PLUS;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_APE;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_APTX;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_APTX_ADAPTIVE;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_APTX_ADAPTIVE_QLEA;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_APTX_ADAPTIVE_R4;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_APTX_HD;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_APTX_TWSP;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_CELT;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_DEFAULT;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_DOLBY_TRUEHD;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_DRA;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_DSD;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_DTS;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_DTS_HD;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_DTS_HD_MA;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_DTS_UHD;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_DTS_UHD_P2;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_EVRC;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_EVRCB;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_EVRCNW;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_EVRCWB;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_E_AC3;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_E_AC3_JOC;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_FLAC;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_HE_AAC_V1;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_HE_AAC_V2;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IEC60958;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_IEC61937;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_LC3;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_LDAC;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_LHDC;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_LHDC_LL;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_MAT;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_MAT_1_0;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_MAT_2_0;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_MAT_2_1;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_MP2;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_MP3;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_MPEGH_BL_L3;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_MPEGH_BL_L4;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_MPEGH_LC_L3;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_MPEGH_LC_L4;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_OPUS;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_PCM_16_BIT;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_PCM_24_BIT_PACKED;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_PCM_32_BIT;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_PCM_8_24_BIT;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_PCM_8_BIT;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_PCM_FLOAT;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_QCELP;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_SBC;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_VORBIS;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_WMA;
+    enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_WMA_PRO;
+  }
+
+  public enum AudioGainMode {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.AudioGainMode AUDIO_GAIN_MODE_CHANNELS;
+    enum_constant public static final android.audio.policy.configuration.AudioGainMode AUDIO_GAIN_MODE_JOINT;
+    enum_constant public static final android.audio.policy.configuration.AudioGainMode AUDIO_GAIN_MODE_RAMP;
+  }
+
+  public enum AudioInOutFlag {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_DIRECT;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_FAST;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_HW_AV_SYNC;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_HW_HOTWORD;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_MMAP_NOIRQ;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_RAW;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_SYNC;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_ULTRASOUND;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_VOIP_TX;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT_PCM;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_FAST;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_NON_BLOCKING;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_PRIMARY;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_RAW;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_SPATIALIZER;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_SYNC;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_TTS;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_ULTRASOUND;
+    enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_VOIP_RX;
+  }
+
+  public class AudioPolicyConfiguration {
+    ctor public AudioPolicyConfiguration();
+    method @Nullable public android.audio.policy.configuration.GlobalConfiguration getGlobalConfiguration();
+    method @Nullable public java.util.List<android.audio.policy.configuration.Modules> getModules();
+    method @Nullable public android.audio.policy.configuration.SurroundSound getSurroundSound();
+    method @Nullable public android.audio.policy.configuration.Version getVersion();
+    method @Nullable public java.util.List<android.audio.policy.configuration.Volumes> getVolumes();
+    method public void setGlobalConfiguration(@Nullable android.audio.policy.configuration.GlobalConfiguration);
+    method public void setSurroundSound(@Nullable android.audio.policy.configuration.SurroundSound);
+    method public void setVersion(@Nullable android.audio.policy.configuration.Version);
+  }
+
+  public enum AudioSource {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_CAMCORDER;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_DEFAULT;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_ECHO_REFERENCE;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_FM_TUNER;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_HOTWORD;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_MIC;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_REMOTE_SUBMIX;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_ULTRASOUND;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_UNPROCESSED;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_VOICE_CALL;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_VOICE_COMMUNICATION;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_VOICE_DOWNLINK;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_VOICE_PERFORMANCE;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_VOICE_RECOGNITION;
+    enum_constant public static final android.audio.policy.configuration.AudioSource AUDIO_SOURCE_VOICE_UPLINK;
+  }
+
+  public enum AudioStreamType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_ACCESSIBILITY;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_ALARM;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_ASSISTANT;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_BLUETOOTH_SCO;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_CALL_ASSISTANT;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_DTMF;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_ENFORCED_AUDIBLE;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_MUSIC;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_NOTIFICATION;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_PATCH;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_REROUTING;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_RING;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_SYSTEM;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_TTS;
+    enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_VOICE_CALL;
+  }
+
+  public enum AudioUsage {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ALARM;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ANNOUNCEMENT;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ASSISTANT;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_CALL_ASSISTANT;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_EMERGENCY;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_GAME;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_MEDIA;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_NOTIFICATION;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_NOTIFICATION_EVENT;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_SAFETY;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_UNKNOWN;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_VEHICLE_STATUS;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_VIRTUAL_SOURCE;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION;
+    enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+  }
+
+  public enum DeviceCategory {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.DeviceCategory DEVICE_CATEGORY_EARPIECE;
+    enum_constant public static final android.audio.policy.configuration.DeviceCategory DEVICE_CATEGORY_EXT_MEDIA;
+    enum_constant public static final android.audio.policy.configuration.DeviceCategory DEVICE_CATEGORY_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.DeviceCategory DEVICE_CATEGORY_HEARING_AID;
+    enum_constant public static final android.audio.policy.configuration.DeviceCategory DEVICE_CATEGORY_SPEAKER;
+  }
+
+  public class DevicePorts {
+    ctor public DevicePorts();
+    method @Nullable public java.util.List<android.audio.policy.configuration.DevicePorts.DevicePort> getDevicePort();
+  }
+
+  public static class DevicePorts.DevicePort {
+    ctor public DevicePorts.DevicePort();
+    method @Nullable public String getAddress();
+    method @Nullable public java.util.List<java.lang.String> getEncodedFormats();
+    method @Nullable public android.audio.policy.configuration.Gains getGains();
+    method @Nullable public java.util.List<android.audio.policy.configuration.Profile> getProfile();
+    method @Nullable public android.audio.policy.configuration.Role getRole();
+    method @Nullable public String getTagName();
+    method @Nullable public String getType();
+    method @Nullable public boolean get_default();
+    method public void setAddress(@Nullable String);
+    method public void setEncodedFormats(@Nullable java.util.List<java.lang.String>);
+    method public void setGains(@Nullable android.audio.policy.configuration.Gains);
+    method public void setRole(@Nullable android.audio.policy.configuration.Role);
+    method public void setTagName(@Nullable String);
+    method public void setType(@Nullable String);
+    method public void set_default(@Nullable boolean);
+  }
+
+  public enum EngineSuffix {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.EngineSuffix _default;
+    enum_constant public static final android.audio.policy.configuration.EngineSuffix configurable;
+  }
+
+  public class Gains {
+    ctor public Gains();
+    method @Nullable public java.util.List<android.audio.policy.configuration.Gains.Gain> getGain();
+  }
+
+  public static class Gains.Gain {
+    ctor public Gains.Gain();
+    method @Nullable public android.audio.policy.configuration.AudioChannelMask getChannel_mask();
+    method @Nullable public int getDefaultValueMB();
+    method @Nullable public int getMaxRampMs();
+    method @Nullable public int getMaxValueMB();
+    method @Nullable public int getMinRampMs();
+    method @Nullable public int getMinValueMB();
+    method @Nullable public java.util.List<android.audio.policy.configuration.AudioGainMode> getMode();
+    method @Nullable public String getName();
+    method @Nullable public int getStepValueMB();
+    method @Nullable public boolean getUseForVolume();
+    method public void setChannel_mask(@Nullable android.audio.policy.configuration.AudioChannelMask);
+    method public void setDefaultValueMB(@Nullable int);
+    method public void setMaxRampMs(@Nullable int);
+    method public void setMaxValueMB(@Nullable int);
+    method public void setMinRampMs(@Nullable int);
+    method public void setMinValueMB(@Nullable int);
+    method public void setMode(@Nullable java.util.List<android.audio.policy.configuration.AudioGainMode>);
+    method public void setName(@Nullable String);
+    method public void setStepValueMB(@Nullable int);
+    method public void setUseForVolume(@Nullable boolean);
+  }
+
+  public class GlobalConfiguration {
+    ctor public GlobalConfiguration();
+    method @Nullable public boolean getCall_screen_mode_supported();
+    method @Nullable public android.audio.policy.configuration.EngineSuffix getEngine_library();
+    method @Nullable public boolean getSpeaker_drc_enabled();
+    method public void setCall_screen_mode_supported(@Nullable boolean);
+    method public void setEngine_library(@Nullable android.audio.policy.configuration.EngineSuffix);
+    method public void setSpeaker_drc_enabled(@Nullable boolean);
+  }
+
+  public enum HalVersion {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.HalVersion _2_0;
+    enum_constant public static final android.audio.policy.configuration.HalVersion _3_0;
+  }
+
+  public class MixPorts {
+    ctor public MixPorts();
+    method @Nullable public java.util.List<android.audio.policy.configuration.MixPorts.MixPort> getMixPort();
+  }
+
+  public static class MixPorts.MixPort {
+    ctor public MixPorts.MixPort();
+    method @Nullable public java.util.List<android.audio.policy.configuration.AudioInOutFlag> getFlags();
+    method @Nullable public android.audio.policy.configuration.Gains getGains();
+    method @Nullable public long getMaxActiveCount();
+    method @Nullable public long getMaxOpenCount();
+    method @Nullable public String getName();
+    method @Nullable public java.util.List<android.audio.policy.configuration.AudioUsage> getPreferredUsage();
+    method @Nullable public java.util.List<android.audio.policy.configuration.Profile> getProfile();
+    method @Nullable public long getRecommendedMuteDurationMs();
+    method @Nullable public android.audio.policy.configuration.Role getRole();
+    method public void setFlags(@Nullable java.util.List<android.audio.policy.configuration.AudioInOutFlag>);
+    method public void setGains(@Nullable android.audio.policy.configuration.Gains);
+    method public void setMaxActiveCount(@Nullable long);
+    method public void setMaxOpenCount(@Nullable long);
+    method public void setName(@Nullable String);
+    method public void setPreferredUsage(@Nullable java.util.List<android.audio.policy.configuration.AudioUsage>);
+    method public void setRecommendedMuteDurationMs(@Nullable long);
+    method public void setRole(@Nullable android.audio.policy.configuration.Role);
+  }
+
+  public enum MixType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.MixType mix;
+    enum_constant public static final android.audio.policy.configuration.MixType mux;
+  }
+
+  public class Modules {
+    ctor public Modules();
+    method @Nullable public java.util.List<android.audio.policy.configuration.Modules.Module> getModule();
+  }
+
+  public static class Modules.Module {
+    ctor public Modules.Module();
+    method @Nullable public android.audio.policy.configuration.AttachedDevices getAttachedDevices();
+    method @Nullable public String getDefaultOutputDevice();
+    method @Nullable public android.audio.policy.configuration.DevicePorts getDevicePorts();
+    method @Nullable public android.audio.policy.configuration.HalVersion getHalVersion();
+    method @Nullable public android.audio.policy.configuration.MixPorts getMixPorts();
+    method @Nullable public String getName();
+    method @Nullable public android.audio.policy.configuration.Routes getRoutes();
+    method public void setAttachedDevices(@Nullable android.audio.policy.configuration.AttachedDevices);
+    method public void setDefaultOutputDevice(@Nullable String);
+    method public void setDevicePorts(@Nullable android.audio.policy.configuration.DevicePorts);
+    method public void setHalVersion(@Nullable android.audio.policy.configuration.HalVersion);
+    method public void setMixPorts(@Nullable android.audio.policy.configuration.MixPorts);
+    method public void setName(@Nullable String);
+    method public void setRoutes(@Nullable android.audio.policy.configuration.Routes);
+  }
+
+  public class Profile {
+    ctor public Profile();
+    method @Nullable public java.util.List<android.audio.policy.configuration.AudioChannelMask> getChannelMasks();
+    method @Nullable public android.audio.policy.configuration.AudioEncapsulationType getEncapsulationType();
+    method @Nullable public String getFormat();
+    method @Nullable public String getName();
+    method @Nullable public java.util.List<java.math.BigInteger> getSamplingRates();
+    method public void setChannelMasks(@Nullable java.util.List<android.audio.policy.configuration.AudioChannelMask>);
+    method public void setEncapsulationType(@Nullable android.audio.policy.configuration.AudioEncapsulationType);
+    method public void setFormat(@Nullable String);
+    method public void setName(@Nullable String);
+    method public void setSamplingRates(@Nullable java.util.List<java.math.BigInteger>);
+  }
+
+  public class Reference {
+    ctor public Reference();
+    method @Nullable public String getName();
+    method @Nullable public java.util.List<java.lang.String> getPoint();
+    method public void setName(@Nullable String);
+  }
+
+  public enum Role {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.Role sink;
+    enum_constant public static final android.audio.policy.configuration.Role source;
+  }
+
+  public class Routes {
+    ctor public Routes();
+    method @Nullable public java.util.List<android.audio.policy.configuration.Routes.Route> getRoute();
+  }
+
+  public static class Routes.Route {
+    ctor public Routes.Route();
+    method @Nullable public String getSink();
+    method @Nullable public String getSources();
+    method @Nullable public android.audio.policy.configuration.MixType getType();
+    method public void setSink(@Nullable String);
+    method public void setSources(@Nullable String);
+    method public void setType(@Nullable android.audio.policy.configuration.MixType);
+  }
+
+  public class SurroundFormats {
+    ctor public SurroundFormats();
+    method @Nullable public java.util.List<android.audio.policy.configuration.SurroundFormats.Format> getFormat();
+  }
+
+  public static class SurroundFormats.Format {
+    ctor public SurroundFormats.Format();
+    method @Nullable public String getName();
+    method @Nullable public java.util.List<java.lang.String> getSubformats();
+    method public void setName(@Nullable String);
+    method public void setSubformats(@Nullable java.util.List<java.lang.String>);
+  }
+
+  public class SurroundSound {
+    ctor public SurroundSound();
+    method @Nullable public android.audio.policy.configuration.SurroundFormats getFormats();
+    method public void setFormats(@Nullable android.audio.policy.configuration.SurroundFormats);
+  }
+
+  public enum Version {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.Version _7_0;
+    enum_constant public static final android.audio.policy.configuration.Version _7_1;
+  }
+
+  public class Volume {
+    ctor public Volume();
+    method @Nullable public android.audio.policy.configuration.DeviceCategory getDeviceCategory();
+    method @Nullable public java.util.List<java.lang.String> getPoint();
+    method @Nullable public String getRef();
+    method @Nullable public android.audio.policy.configuration.AudioStreamType getStream();
+    method public void setDeviceCategory(@Nullable android.audio.policy.configuration.DeviceCategory);
+    method public void setRef(@Nullable String);
+    method public void setStream(@Nullable android.audio.policy.configuration.AudioStreamType);
+  }
+
+  public class Volumes {
+    ctor public Volumes();
+    method @Nullable public java.util.List<android.audio.policy.configuration.Reference> getReference();
+    method @Nullable public java.util.List<android.audio.policy.configuration.Volume> getVolume();
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method @Nullable public static android.audio.policy.configuration.AudioPolicyConfiguration read(@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/api/last_current.txt b/audio/aidl/default/config/audioPolicy/api/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/api/last_current.txt
diff --git a/audio/aidl/default/config/audioPolicy/api/last_removed.txt b/audio/aidl/default/config/audioPolicy/api/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/api/last_removed.txt
diff --git a/audio/aidl/default/config/audioPolicy/api/removed.txt b/audio/aidl/default/config/audioPolicy/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/audio/aidl/default/config/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
similarity index 100%
rename from audio/aidl/default/config/audio_policy_configuration.xsd
rename to audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
diff --git a/audio/aidl/default/config/audioPolicy/engine/Android.bp b/audio/aidl/default/config/audioPolicy/engine/Android.bp
new file mode 100644
index 0000000..b2a7310
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/engine/Android.bp
@@ -0,0 +1,15 @@
+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"],
+}
+
+xsd_config {
+    name: "audio_policy_engine_configuration_aidl_default",
+    srcs: ["audio_policy_engine_configuration.xsd"],
+    package_name: "android.audio.policy.engine.configuration",
+    nullability: true,
+}
diff --git a/audio/aidl/default/config/audioPolicy/engine/api/current.txt b/audio/aidl/default/config/audioPolicy/engine/api/current.txt
new file mode 100644
index 0000000..59574f3
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/engine/api/current.txt
@@ -0,0 +1,302 @@
+// Signature format: 2.0
+package android.audio.policy.engine.configuration {
+
+  public class AttributesGroup {
+    ctor public AttributesGroup();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.AttributesType> getAttributes_optional();
+    method @Nullable public android.audio.policy.engine.configuration.BundleType getBundle_optional();
+    method @Nullable public android.audio.policy.engine.configuration.ContentTypeType getContentType_optional();
+    method @Nullable public android.audio.policy.engine.configuration.FlagsType getFlags_optional();
+    method @Nullable public android.audio.policy.engine.configuration.SourceType getSource_optional();
+    method @Nullable public android.audio.policy.engine.configuration.Stream getStreamType();
+    method @Nullable public android.audio.policy.engine.configuration.UsageType getUsage_optional();
+    method @Nullable public String getVolumeGroup();
+    method public void setBundle_optional(@Nullable android.audio.policy.engine.configuration.BundleType);
+    method public void setContentType_optional(@Nullable android.audio.policy.engine.configuration.ContentTypeType);
+    method public void setFlags_optional(@Nullable android.audio.policy.engine.configuration.FlagsType);
+    method public void setSource_optional(@Nullable android.audio.policy.engine.configuration.SourceType);
+    method public void setStreamType(@Nullable android.audio.policy.engine.configuration.Stream);
+    method public void setUsage_optional(@Nullable android.audio.policy.engine.configuration.UsageType);
+    method public void setVolumeGroup(@Nullable String);
+  }
+
+  public class AttributesRef {
+    ctor public AttributesRef();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.AttributesRefType> getReference();
+  }
+
+  public class AttributesRefType {
+    ctor public AttributesRefType();
+    method @Nullable public android.audio.policy.engine.configuration.AttributesType getAttributes();
+    method @Nullable public String getName();
+    method public void setAttributes(@Nullable android.audio.policy.engine.configuration.AttributesType);
+    method public void setName(@Nullable String);
+  }
+
+  public class AttributesType {
+    ctor public AttributesType();
+    method @Nullable public String getAttributesRef();
+    method @Nullable public android.audio.policy.engine.configuration.BundleType getBundle();
+    method @Nullable public android.audio.policy.engine.configuration.ContentTypeType getContentType();
+    method @Nullable public android.audio.policy.engine.configuration.FlagsType getFlags();
+    method @Nullable public android.audio.policy.engine.configuration.SourceType getSource();
+    method @Nullable public android.audio.policy.engine.configuration.UsageType getUsage();
+    method public void setAttributesRef(@Nullable String);
+    method public void setBundle(@Nullable android.audio.policy.engine.configuration.BundleType);
+    method public void setContentType(@Nullable android.audio.policy.engine.configuration.ContentTypeType);
+    method public void setFlags(@Nullable android.audio.policy.engine.configuration.FlagsType);
+    method public void setSource(@Nullable android.audio.policy.engine.configuration.SourceType);
+    method public void setUsage(@Nullable android.audio.policy.engine.configuration.UsageType);
+  }
+
+  public class BundleType {
+    ctor public BundleType();
+    method @Nullable public String getKey();
+    method @Nullable public String getValue();
+    method public void setKey(@Nullable String);
+    method public void setValue(@Nullable String);
+  }
+
+  public class Configuration {
+    ctor public Configuration();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.AttributesRef> getAttributesRef();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.CriteriaType> getCriteria();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.CriterionTypesType> getCriterion_types();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.ProductStrategies> getProductStrategies();
+    method @Nullable public android.audio.policy.engine.configuration.Version getVersion();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.VolumeGroupsType> getVolumeGroups();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.VolumesType> getVolumes();
+    method public void setVersion(@Nullable android.audio.policy.engine.configuration.Version);
+  }
+
+  public enum ContentType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.ContentType AUDIO_CONTENT_TYPE_MOVIE;
+    enum_constant public static final android.audio.policy.engine.configuration.ContentType AUDIO_CONTENT_TYPE_MUSIC;
+    enum_constant public static final android.audio.policy.engine.configuration.ContentType AUDIO_CONTENT_TYPE_SONIFICATION;
+    enum_constant public static final android.audio.policy.engine.configuration.ContentType AUDIO_CONTENT_TYPE_SPEECH;
+    enum_constant public static final android.audio.policy.engine.configuration.ContentType AUDIO_CONTENT_TYPE_UNKNOWN;
+  }
+
+  public class ContentTypeType {
+    ctor public ContentTypeType();
+    method @Nullable public android.audio.policy.engine.configuration.ContentType getValue();
+    method public void setValue(@Nullable android.audio.policy.engine.configuration.ContentType);
+  }
+
+  public class CriteriaType {
+    ctor public CriteriaType();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.CriterionType> getCriterion();
+  }
+
+  public class CriterionType {
+    ctor public CriterionType();
+    method @Nullable public String getName();
+    method @Nullable public String getType();
+    method @Nullable public String get_default();
+    method public void setName(@Nullable String);
+    method public void setType(@Nullable String);
+    method public void set_default(@Nullable String);
+  }
+
+  public class CriterionTypeType {
+    ctor public CriterionTypeType();
+    method @Nullable public String getName();
+    method @Nullable public android.audio.policy.engine.configuration.PfwCriterionTypeEnum getType();
+    method @Nullable public android.audio.policy.engine.configuration.ValuesType getValues();
+    method public void setName(@Nullable String);
+    method public void setType(@Nullable android.audio.policy.engine.configuration.PfwCriterionTypeEnum);
+    method public void setValues(@Nullable android.audio.policy.engine.configuration.ValuesType);
+  }
+
+  public class CriterionTypesType {
+    ctor public CriterionTypesType();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.CriterionTypeType> getCriterion_type();
+  }
+
+  public enum DeviceCategory {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.DeviceCategory DEVICE_CATEGORY_EARPIECE;
+    enum_constant public static final android.audio.policy.engine.configuration.DeviceCategory DEVICE_CATEGORY_EXT_MEDIA;
+    enum_constant public static final android.audio.policy.engine.configuration.DeviceCategory DEVICE_CATEGORY_HEADSET;
+    enum_constant public static final android.audio.policy.engine.configuration.DeviceCategory DEVICE_CATEGORY_HEARING_AID;
+    enum_constant public static final android.audio.policy.engine.configuration.DeviceCategory DEVICE_CATEGORY_SPEAKER;
+  }
+
+  public enum FlagType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_AUDIBILITY_ENFORCED;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_BEACON;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_BYPASS_MUTE;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_CAPTURE_PRIVATE;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_DEEP_BUFFER;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_HW_AV_SYNC;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_HW_HOTWORD;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_LOW_LATENCY;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_MUTE_HAPTIC;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_NONE;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_NO_MEDIA_PROJECTION;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_NO_SYSTEM_CAPTURE;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_SCO;
+    enum_constant public static final android.audio.policy.engine.configuration.FlagType AUDIO_FLAG_SECURE;
+  }
+
+  public class FlagsType {
+    ctor public FlagsType();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.FlagType> getValue();
+    method public void setValue(@Nullable java.util.List<android.audio.policy.engine.configuration.FlagType>);
+  }
+
+  public enum PfwCriterionTypeEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.PfwCriterionTypeEnum exclusive;
+    enum_constant public static final android.audio.policy.engine.configuration.PfwCriterionTypeEnum inclusive;
+  }
+
+  public class ProductStrategies {
+    ctor public ProductStrategies();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.ProductStrategies.ProductStrategy> getProductStrategy();
+  }
+
+  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 String getName();
+    method public void setName(@Nullable String);
+  }
+
+  public enum SourceEnumType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_CAMCORDER;
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_DEFAULT;
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_ECHO_REFERENCE;
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_FM_TUNER;
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_MIC;
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_REMOTE_SUBMIX;
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_UNPROCESSED;
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_VOICE_CALL;
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_VOICE_COMMUNICATION;
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_VOICE_DOWNLINK;
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_VOICE_PERFORMANCE;
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_VOICE_RECOGNITION;
+    enum_constant public static final android.audio.policy.engine.configuration.SourceEnumType AUDIO_SOURCE_VOICE_UPLINK;
+  }
+
+  public class SourceType {
+    ctor public SourceType();
+    method @Nullable public android.audio.policy.engine.configuration.SourceEnumType getValue();
+    method public void setValue(@Nullable android.audio.policy.engine.configuration.SourceEnumType);
+  }
+
+  public enum Stream {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_ACCESSIBILITY;
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_ALARM;
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_ASSISTANT;
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_BLUETOOTH_SCO;
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_DEFAULT;
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_DTMF;
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_ENFORCED_AUDIBLE;
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_MUSIC;
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_NOTIFICATION;
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_RING;
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_SYSTEM;
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_TTS;
+    enum_constant public static final android.audio.policy.engine.configuration.Stream AUDIO_STREAM_VOICE_CALL;
+  }
+
+  public enum UsageEnumType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_ALARM;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_ASSISTANT;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_CALL_ASSISTANT;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_GAME;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_MEDIA;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_NOTIFICATION;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_NOTIFICATION_EVENT;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_UNKNOWN;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_VIRTUAL_SOURCE;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION;
+    enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+  }
+
+  public class UsageType {
+    ctor public UsageType();
+    method @Nullable public android.audio.policy.engine.configuration.UsageEnumType getValue();
+    method public void setValue(@Nullable android.audio.policy.engine.configuration.UsageEnumType);
+  }
+
+  public class ValueType {
+    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 {
+    ctor public ValuesType();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.ValueType> getValue();
+  }
+
+  public enum Version {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.Version _1_0;
+  }
+
+  public class Volume {
+    ctor public Volume();
+    method @Nullable public android.audio.policy.engine.configuration.DeviceCategory getDeviceCategory();
+    method @Nullable public java.util.List<java.lang.String> getPoint();
+    method @Nullable public String getRef();
+    method public void setDeviceCategory(@Nullable android.audio.policy.engine.configuration.DeviceCategory);
+    method public void setRef(@Nullable String);
+  }
+
+  public class VolumeGroupsType {
+    ctor public VolumeGroupsType();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.VolumeGroupsType.VolumeGroup> getVolumeGroup();
+  }
+
+  public static class VolumeGroupsType.VolumeGroup {
+    ctor public VolumeGroupsType.VolumeGroup();
+    method @Nullable public int getIndexMax();
+    method @Nullable public int getIndexMin();
+    method @Nullable public String getName();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.Volume> getVolume();
+    method public void setIndexMax(@Nullable int);
+    method public void setIndexMin(@Nullable int);
+    method public void setName(@Nullable String);
+  }
+
+  public class VolumeRef {
+    ctor public VolumeRef();
+    method @Nullable public String getName();
+    method @Nullable public java.util.List<java.lang.String> getPoint();
+    method public void setName(@Nullable String);
+  }
+
+  public class VolumesType {
+    ctor public VolumesType();
+    method @Nullable public java.util.List<android.audio.policy.engine.configuration.VolumeRef> getReference();
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method @Nullable public static android.audio.policy.engine.configuration.Configuration read(@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/engine/api/last_current.txt b/audio/aidl/default/config/audioPolicy/engine/api/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/engine/api/last_current.txt
diff --git a/audio/aidl/default/config/audioPolicy/engine/api/last_removed.txt b/audio/aidl/default/config/audioPolicy/engine/api/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/engine/api/last_removed.txt
diff --git a/audio/aidl/default/config/audioPolicy/engine/api/removed.txt b/audio/aidl/default/config/audioPolicy/engine/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/engine/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
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
new file mode 100644
index 0000000..b58a6c8
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
@@ -0,0 +1,418 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- 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.
+     -->
+
+ <xs:schema version="2.0"
+            elementFormDefault="qualified"
+            attributeFormDefault="unqualified"
+            xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <!-- List the config versions supported by audio policy engine. -->
+    <xs:simpleType name="version">
+        <xs:restriction base="xs:decimal">
+            <xs:enumeration value="1.0"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:element name="configuration">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="ProductStrategies" type="ProductStrategies"  minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="criterion_types" type="criterionTypesType"  minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="criteria" type="criteriaType"  minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="volumeGroups" type="volumeGroupsType"  minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="volumes" type="volumesType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="attributesRef" type="attributesRef"  minOccurs="0" maxOccurs="unbounded"/>
+            </xs:sequence>
+            <xs:attribute name="version" type="version" use="required"/>
+        </xs:complexType>
+
+        <xs:key name="volumeCurveNameKey">
+            <xs:selector xpath="volumes/reference"/>
+            <xs:field xpath="@name"/>
+        </xs:key>
+        <xs:keyref name="volumeCurveRef" refer="volumeCurveNameKey">
+            <xs:selector xpath="volumeGroups/volumeGroup"/>
+            <xs:field xpath="@ref"/>
+        </xs:keyref>
+
+        <xs:key name="attributesRefNameKey">
+            <xs:selector xpath="attributesRef/reference"/>
+            <xs:field xpath="@name"/>
+        </xs:key>
+        <xs:keyref name="volumeGroupAttributesRef" refer="attributesRefNameKey">
+            <xs:selector xpath="volumeGroups/volumeGroup/volume"/>
+            <xs:field xpath="@attributesRef"/>
+        </xs:keyref>
+        <xs:keyref name="ProductStrategyAttributesRef" refer="attributesRefNameKey">
+            <xs:selector xpath="ProductStrategies/ProductStrategy/Attributes"/>
+            <xs:field xpath="@attributesRef"/>
+        </xs:keyref>
+
+        <xs:unique name="productStrategyNameUniqueness">
+            <xs:selector xpath="ProductStrategies/ProductStrategy"/>
+            <xs:field xpath="@name"/>
+        </xs:unique>
+
+        <!-- ensure validity of volume group referred in product strategy-->
+        <xs:key name="volumeGroupKey">
+            <xs:selector xpath="volumeGroups/volumeGroup/name"/>
+            <xs:field xpath="."/>
+        </xs:key>
+        <xs:keyref name="volumeGroupRef" refer="volumeGroupKey">
+            <xs:selector xpath="ProductStrategies/ProductStrategy/AttributesGroup"/>
+            <xs:field xpath="@volumeGroup"/>
+        </xs:keyref>
+
+        <xs:unique name="volumeTargetUniqueness">
+            <xs:selector xpath="volumeGroups/volumeGroup"/>
+            <xs:field xpath="@name"/>
+            <xs:field xpath="@deviceCategory"/>
+        </xs:unique>
+
+        <!-- ensure validity of criterion type referred in criterion-->
+        <xs:key name="criterionTypeKey">
+            <xs:selector xpath="criterion_types/criterion_type"/>
+            <xs:field xpath="@name"/>
+        </xs:key>
+        <xs:keyref name="criterionTypeKeyRef" refer="criterionTypeKey">
+            <xs:selector xpath="criteria/criterion"/>
+            <xs:field xpath="@type"/>
+        </xs:keyref>
+
+    </xs:element>
+
+    <xs:complexType name="ProductStrategies">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="ProductStrategy" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="AttributesGroup" type="AttributesGroup" minOccurs="1" maxOccurs="unbounded"/>
+                    </xs:sequence>
+                    <xs:attribute name="name" type="xs:string" use="required"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="AttributesGroup">
+        <xs:sequence>
+            <xs:choice minOccurs="0">
+                <xs:element name="Attributes" type="AttributesType" minOccurs="1" maxOccurs="unbounded"/>
+                <xs:sequence>
+                    <xs:element name="ContentType" type="ContentTypeType" minOccurs="0" maxOccurs="1"/>
+                    <xs:element name="Usage" type="UsageType" minOccurs="1" maxOccurs="1"/>
+                    <xs:element name="Source" type="SourceType" minOccurs="0" maxOccurs="1"/>
+                    <xs:element name="Flags" type="FlagsType" minOccurs="0" maxOccurs="1"/>
+                    <xs:element name="Bundle" type="BundleType" minOccurs="0" maxOccurs="1"/>
+                </xs:sequence>
+            </xs:choice>
+        </xs:sequence>
+        <xs:attribute name="streamType" type="stream" use="optional"/>
+        <xs:attribute name="volumeGroup" type="xs:string" use="optional"/>
+    </xs:complexType>
+
+    <xs:complexType name="volumeGroupsType">
+        <xs:sequence>
+             <xs:element name="volumeGroup" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                         <xs:element name="name" type="xs:token"/>
+                         <xs:element name="indexMin" type="xs:int" minOccurs="0" maxOccurs="1"/>
+                         <xs:element name="indexMax" type="xs:int" minOccurs="0" maxOccurs="1"/>
+                         <xs:element name="volume" type="volume" minOccurs="1" maxOccurs="unbounded"/>
+                     </xs:sequence>
+                </xs:complexType>
+                <xs:unique name="volumeAttributesUniqueness">
+                    <xs:selector xpath="volume"/>
+                    <xs:field xpath="deviceCategory"/>
+                </xs:unique>
+             </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="volumesType">
+        <xs:sequence>
+            <xs:element name="reference" type="volumeRef" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="attributesRef">
+        <xs:sequence>
+            <xs:element name="reference" type="attributesRefType" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="criteriaType">
+        <xs:sequence>
+            <xs:element name="criterion" type="criterionType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="criterionType">
+        <xs:attribute name="name" type="xs:string" use="required"/>
+        <xs:attribute name="type" type="xs:string" use="required"/>
+        <xs:attribute name="default" type="xs:string" use="optional"/>
+    </xs:complexType>
+
+    <xs:complexType name="criterionTypesType">
+        <xs:sequence>
+            <xs:element name="criterion_type" type="criterionTypeType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="criterionTypeType">
+        <xs:sequence>
+            <xs:element name="values" type="valuesType" minOccurs="0" maxOccurs="1"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:token" use="required"/>
+        <xs:attribute name="type" type="pfwCriterionTypeEnum" use="required"/>
+    </xs:complexType>
+
+    <xs:complexType name="valuesType">
+        <xs:sequence>
+            <xs:element name="value" type="valueType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="valueType">
+        <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>
+
+    <xs:simpleType name="longDecimalOrHexType">
+      <xs:union memberTypes="xs:long longHexType" />
+    </xs:simpleType>
+
+    <xs:simpleType name="longHexType">
+      <xs:restriction base="xs:string">
+        <xs:pattern value="0x[0-9A-Fa-f]{1,16}"/>
+      </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="attributesRefType">
+        <xs:sequence>
+            <xs:element name="Attributes" type="AttributesType" minOccurs="1" maxOccurs="1"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:token" use="required"/>
+    </xs:complexType>
+
+    <xs:complexType name="AttributesType">
+        <xs:sequence>
+            <xs:element name="ContentType" type="ContentTypeType" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="Usage" type="UsageType" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="Source" type="SourceType" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="Flags" type="FlagsType" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="Bundle" type="BundleType" minOccurs="0" maxOccurs="1"/>
+        </xs:sequence>
+        <xs:attribute name="attributesRef" type="xs:token" use="optional"/>
+        <!-- with xsd 1.1, it is impossible to make choice on either attributes or element...-->
+    </xs:complexType>
+
+    <xs:complexType name="ContentTypeType">
+        <xs:attribute name="value" type="contentType" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="UsageType">
+        <xs:attribute name="value" type="usageEnumType" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="SourceType">
+        <xs:attribute name="value" type="sourceEnumType" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="FlagsType">
+        <xs:attribute name="value" type="flagsEnumType" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="BundleType">
+        <xs:attribute name="key" type="xs:string" use="required"/>
+        <xs:attribute name="value" type="xs:string" use="required"/>
+    </xs:complexType>
+
+    <xs:complexType name="volume">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Volume section defines a volume curve for a given use case and device category.
+                It contains a list of points of this curve expressing the attenuation in Millibels
+                for a given volume index from 0 to 100.
+                <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+                    <point>0,-9600</point>
+                    <point>100,0</point>
+                </volume>
+
+                It may also reference a reference/@name to avoid duplicating curves.
+                <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+                <reference name="DEFAULT_MEDIA_VOLUME_CURVE">
+                    <point>0,-9600</point>
+                    <point>100,0</point>
+                </reference>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="point" type="volumePoint" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="deviceCategory" type="deviceCategory"/>
+        <xs:attribute name="ref" type="xs:token" use="optional"/>
+    </xs:complexType>
+
+    <xs:complexType name="volumeRef">
+        <xs:sequence>
+            <xs:element name="point" type="volumePoint" minOccurs="2" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:token" use="required"/>
+    </xs:complexType>
+
+    <xs:simpleType name="volumePoint">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Comma separated pair of number.
+                The fist one is the framework level (between 0 and 100).
+                The second one is the volume to send to the HAL.
+                The framework will interpolate volumes not specified.
+                Their MUST be at least 2 points specified.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:pattern value="([0-9]{1,2}|100),-?[0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+
+    <xs:simpleType name="streamsCsv">
+        <xs:list>
+            <xs:simpleType>
+                <xs:restriction base="stream">
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:list>
+    </xs:simpleType>
+
+    <!-- Enum values of audio_stream_type_t in audio-base.h
+         TODO: avoid manual sync. -->
+    <xs:simpleType name="stream">
+        <xs:restriction base="xs:NMTOKEN">
+            <!--xs:pattern value="\c+(,\c+)*"/-->
+            <xs:enumeration value="AUDIO_STREAM_DEFAULT"/>
+            <xs:enumeration value="AUDIO_STREAM_VOICE_CALL"/>
+            <xs:enumeration value="AUDIO_STREAM_SYSTEM"/>
+            <xs:enumeration value="AUDIO_STREAM_RING"/>
+            <xs:enumeration value="AUDIO_STREAM_MUSIC"/>
+            <xs:enumeration value="AUDIO_STREAM_ALARM"/>
+            <xs:enumeration value="AUDIO_STREAM_NOTIFICATION"/>
+            <xs:enumeration value="AUDIO_STREAM_BLUETOOTH_SCO"/>
+            <xs:enumeration value="AUDIO_STREAM_ENFORCED_AUDIBLE"/>
+            <xs:enumeration value="AUDIO_STREAM_DTMF"/>
+            <xs:enumeration value="AUDIO_STREAM_TTS"/>
+            <xs:enumeration value="AUDIO_STREAM_ACCESSIBILITY"/>
+            <xs:enumeration value="AUDIO_STREAM_ASSISTANT"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="deviceCategory">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="DEVICE_CATEGORY_HEADSET"/>
+            <xs:enumeration value="DEVICE_CATEGORY_SPEAKER"/>
+            <xs:enumeration value="DEVICE_CATEGORY_EARPIECE"/>
+            <xs:enumeration value="DEVICE_CATEGORY_EXT_MEDIA"/>
+            <xs:enumeration value="DEVICE_CATEGORY_HEARING_AID"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="contentType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_CONTENT_TYPE_UNKNOWN"/>
+            <xs:enumeration value="AUDIO_CONTENT_TYPE_SPEECH"/>
+            <xs:enumeration value="AUDIO_CONTENT_TYPE_MUSIC"/>
+            <xs:enumeration value="AUDIO_CONTENT_TYPE_MOVIE"/>
+            <xs:enumeration value="AUDIO_CONTENT_TYPE_SONIFICATION"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="usageEnumType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_USAGE_UNKNOWN"/>
+            <xs:enumeration value="AUDIO_USAGE_MEDIA"/>
+            <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION"/>
+            <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/>
+            <xs:enumeration value="AUDIO_USAGE_ALARM"/>
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION"/>
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/>
+            <!-- Note: the following 3 values were deprecated in Android T (13) SDK -->
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/>
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/>
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/>
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_EVENT"/>
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/>
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/>
+            <xs:enumeration value="AUDIO_USAGE_GAME"/>
+            <xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE"/>
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANT"/>
+            <xs:enumeration value="AUDIO_USAGE_CALL_ASSISTANT"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="flagsEnumType">
+        <xs:list>
+            <xs:simpleType>
+                <xs:restriction base="flagType">
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:list>
+    </xs:simpleType>
+
+    <xs:simpleType name="flagType">
+        <xs:restriction base="xs:NMTOKEN">
+            <xs:enumeration value="AUDIO_FLAG_NONE"/>
+            <xs:enumeration value="AUDIO_FLAG_AUDIBILITY_ENFORCED"/>
+            <xs:enumeration value="AUDIO_FLAG_SECURE"/>
+            <xs:enumeration value="AUDIO_FLAG_SCO"/>
+            <xs:enumeration value="AUDIO_FLAG_BEACON"/>
+            <xs:enumeration value="AUDIO_FLAG_HW_AV_SYNC"/>
+            <xs:enumeration value="AUDIO_FLAG_HW_HOTWORD"/>
+            <xs:enumeration value="AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY"/>
+            <xs:enumeration value="AUDIO_FLAG_BYPASS_MUTE"/>
+            <xs:enumeration value="AUDIO_FLAG_LOW_LATENCY"/>
+            <xs:enumeration value="AUDIO_FLAG_DEEP_BUFFER"/>
+            <xs:enumeration value="AUDIO_FLAG_NO_MEDIA_PROJECTION"/>
+            <xs:enumeration value="AUDIO_FLAG_MUTE_HAPTIC"/>
+            <xs:enumeration value="AUDIO_FLAG_NO_SYSTEM_CAPTURE"/>
+            <xs:enumeration value="AUDIO_FLAG_CAPTURE_PRIVATE"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="sourceEnumType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_SOURCE_DEFAULT"/>
+            <xs:enumeration value="AUDIO_SOURCE_MIC"/>
+            <xs:enumeration value="AUDIO_SOURCE_VOICE_UPLINK"/>
+            <xs:enumeration value="AUDIO_SOURCE_VOICE_DOWNLINK"/>
+            <xs:enumeration value="AUDIO_SOURCE_VOICE_CALL"/>
+            <xs:enumeration value="AUDIO_SOURCE_CAMCORDER"/>
+            <xs:enumeration value="AUDIO_SOURCE_VOICE_RECOGNITION"/>
+            <xs:enumeration value="AUDIO_SOURCE_VOICE_COMMUNICATION"/>
+            <xs:enumeration value="AUDIO_SOURCE_REMOTE_SUBMIX"/>
+            <xs:enumeration value="AUDIO_SOURCE_UNPROCESSED"/>
+            <xs:enumeration value="AUDIO_SOURCE_VOICE_PERFORMANCE"/>
+            <xs:enumeration value="AUDIO_SOURCE_ECHO_REFERENCE"/>
+            <xs:enumeration value="AUDIO_SOURCE_FM_TUNER"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="pfwCriterionTypeEnum">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="inclusive"/>
+            <xs:enumeration value="exclusive"/>
+        </xs:restriction>
+    </xs:simpleType>
+</xs:schema>
diff --git a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
index 3920a58..39345a9 100644
--- a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
+++ b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
@@ -25,6 +25,7 @@
 
 #include "DynamicsProcessingSw.h"
 
+using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::DynamicsProcessingSw;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::kDynamicsProcessingSwImplUUID;
@@ -47,23 +48,31 @@
     }
 }
 
-extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
-    if (!instanceSp) {
-        return EX_NONE;
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kDynamicsProcessingSwImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
     }
-    State state;
-    ndk::ScopedAStatus status = instanceSp->getState(&state);
-    if (!status.isOk() || State::INIT != state) {
-        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
-                   << " in state: " << toString(state) << ", status: " << status.getDescription();
-        return EX_ILLEGAL_STATE;
-    }
-    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+    *_aidl_return = DynamicsProcessingSw::kDescriptor;
     return EX_NONE;
 }
 
 namespace aidl::android::hardware::audio::effect {
 
+const std::string DynamicsProcessingSw::kEffectName = "DynamicsProcessingSw";
+const DynamicsProcessing::Capability DynamicsProcessingSw::kCapability;
+const Descriptor DynamicsProcessingSw::kDescriptor = {
+        .common = {.id = {.type = kDynamicsProcessingTypeUUID,
+                          .uuid = kDynamicsProcessingSwImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = DynamicsProcessingSw::kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = Capability::make<Capability::dynamicsProcessing>(
+                DynamicsProcessingSw::kCapability)};
+
 ndk::ScopedAStatus DynamicsProcessingSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
     *_aidl_return = kDescriptor;
@@ -73,8 +82,6 @@
 ndk::ScopedAStatus DynamicsProcessingSw::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
-    std::lock_guard lg(mMutex);
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     mSpecificParam = specific.get<Parameter::Specific::dynamicsProcessing>();
     LOG(DEBUG) << __func__ << " success with: " << specific.toString();
@@ -93,9 +100,13 @@
         const Parameter::Common& common) {
     if (mContext) {
         LOG(DEBUG) << __func__ << " context already exist";
-        return mContext;
+    } else {
+        mContext = std::make_shared<DynamicsProcessingSwContext>(1 /* statusFmqDepth */, common);
     }
-    mContext = std::make_shared<DynamicsProcessingSwContext>(1 /* statusFmqDepth */, common);
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> DynamicsProcessingSw::getContext() {
     return mContext;
 }
 
@@ -107,13 +118,13 @@
 }
 
 // Processing method running in EffectWorker thread.
-IEffect::Status DynamicsProcessingSw::effectProcessImpl(float* in, float* out, int process) {
+IEffect::Status DynamicsProcessingSw::effectProcessImpl(float* in, float* out, int samples) {
     // TODO: get data buffer and process.
-    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
-    for (int i = 0; i < process; i++) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    for (int i = 0; i < samples; i++) {
         *out++ = *in++;
     }
-    return {STATUS_OK, process, process};
+    return {STATUS_OK, samples, samples};
 }
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
index 2bc2762..2ae46c5 100644
--- a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
+++ b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
@@ -37,6 +37,9 @@
 
 class DynamicsProcessingSw final : public EffectImpl {
   public:
+    static const std::string kEffectName;
+    static const DynamicsProcessing::Capability kCapability;
+    static const Descriptor kDescriptor;
     DynamicsProcessingSw() { LOG(DEBUG) << __func__; }
     ~DynamicsProcessingSw() {
         cleanUp();
@@ -47,26 +50,16 @@
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
     ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
                                             Parameter::Specific* specific) override;
-    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+
     std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
     RetCode releaseContext() override;
 
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+    std::string getEffectName() override { return kEffectName; };
+
   private:
     std::shared_ptr<DynamicsProcessingSwContext> mContext;
-    /* capabilities */
-    const DynamicsProcessing::Capability kCapability;
-    /* Effect descriptor */
-    const Descriptor kDescriptor = {
-            .common = {.id = {.type = kDynamicsProcessingTypeUUID,
-                              .uuid = kDynamicsProcessingSwImplUUID,
-                              .proxy = std::nullopt},
-                       .flags = {.type = Flags::Type::INSERT,
-                                 .insert = Flags::Insert::FIRST,
-                                 .volume = Flags::Volume::CTRL},
-                       .name = "DynamicsProcessingSw",
-                       .implementor = "The Android Open Source Project"},
-            .capability = Capability::make<Capability::dynamicsProcessing>(kCapability)};
-
     /* parameters */
     DynamicsProcessing mSpecificParam;
 };
diff --git a/audio/aidl/default/envReverb/EnvReverbSw.cpp b/audio/aidl/default/envReverb/EnvReverbSw.cpp
index ad447ab..a107064 100644
--- a/audio/aidl/default/envReverb/EnvReverbSw.cpp
+++ b/audio/aidl/default/envReverb/EnvReverbSw.cpp
@@ -25,6 +25,7 @@
 
 #include "EnvReverbSw.h"
 
+using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::EnvReverbSw;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::kEnvReverbSwImplUUID;
@@ -47,23 +48,30 @@
     }
 }
 
-extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
-    if (!instanceSp) {
-        return EX_NONE;
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kEnvReverbSwImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
     }
-    State state;
-    ndk::ScopedAStatus status = instanceSp->getState(&state);
-    if (!status.isOk() || State::INIT != state) {
-        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
-                   << " in state: " << toString(state) << ", status: " << status.getDescription();
-        return EX_ILLEGAL_STATE;
-    }
-    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+    *_aidl_return = EnvReverbSw::kDescriptor;
     return EX_NONE;
 }
 
 namespace aidl::android::hardware::audio::effect {
 
+const std::string EnvReverbSw::kEffectName = "EnvReverbSw";
+const EnvironmentalReverb::Capability EnvReverbSw::kCapability;
+const Descriptor EnvReverbSw::kDescriptor = {
+        .common = {.id = {.type = kEnvReverbTypeUUID,
+                          .uuid = kEnvReverbSwImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = EnvReverbSw::kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = Capability::make<Capability::environmentalReverb>(EnvReverbSw::kCapability)};
+
 ndk::ScopedAStatus EnvReverbSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
     *_aidl_return = kDescriptor;
@@ -71,12 +79,10 @@
 }
 
 ndk::ScopedAStatus EnvReverbSw::setParameterSpecific(const Parameter::Specific& specific) {
-    RETURN_IF(Parameter::Specific::reverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+    RETURN_IF(Parameter::Specific::environmentalReverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
-    std::lock_guard lg(mMutex);
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
-    mSpecificParam = specific.get<Parameter::Specific::reverb>();
+    mSpecificParam = specific.get<Parameter::Specific::environmentalReverb>();
     LOG(DEBUG) << __func__ << " success with: " << specific.toString();
     return ndk::ScopedAStatus::ok();
 }
@@ -84,17 +90,22 @@
 ndk::ScopedAStatus EnvReverbSw::getParameterSpecific(const Parameter::Id& id,
                                                      Parameter::Specific* specific) {
     auto tag = id.getTag();
-    RETURN_IF(Parameter::Id::reverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
-    specific->set<Parameter::Specific::reverb>(mSpecificParam);
+    RETURN_IF(Parameter::Id::environmentalReverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    specific->set<Parameter::Specific::environmentalReverb>(mSpecificParam);
     return ndk::ScopedAStatus::ok();
 }
 
 std::shared_ptr<EffectContext> EnvReverbSw::createContext(const Parameter::Common& common) {
     if (mContext) {
         LOG(DEBUG) << __func__ << " context already exist";
-        return mContext;
+    } else {
+        mContext = std::make_shared<EnvReverbSwContext>(1 /* statusFmqDepth */, common);
     }
-    mContext = std::make_shared<EnvReverbSwContext>(1 /* statusFmqDepth */, common);
+
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> EnvReverbSw::getContext() {
     return mContext;
 }
 
@@ -106,13 +117,13 @@
 }
 
 // Processing method running in EffectWorker thread.
-IEffect::Status EnvReverbSw::effectProcessImpl(float* in, float* out, int process) {
+IEffect::Status EnvReverbSw::effectProcessImpl(float* in, float* out, int samples) {
     // TODO: get data buffer and process.
-    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
-    for (int i = 0; i < process; i++) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    for (int i = 0; i < samples; i++) {
         *out++ = *in++;
     }
-    return {STATUS_OK, process, process};
+    return {STATUS_OK, samples, samples};
 }
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/envReverb/EnvReverbSw.h b/audio/aidl/default/envReverb/EnvReverbSw.h
index 5a9ab27..b8761a6 100644
--- a/audio/aidl/default/envReverb/EnvReverbSw.h
+++ b/audio/aidl/default/envReverb/EnvReverbSw.h
@@ -37,6 +37,9 @@
 
 class EnvReverbSw final : public EffectImpl {
   public:
+    static const std::string kEffectName;
+    static const EnvironmentalReverb::Capability kCapability;
+    static const Descriptor kDescriptor;
     EnvReverbSw() { LOG(DEBUG) << __func__; }
     ~EnvReverbSw() {
         cleanUp();
@@ -47,27 +50,17 @@
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
     ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
                                             Parameter::Specific* specific) override;
-    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+
     std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
     RetCode releaseContext() override;
 
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+    std::string getEffectName() override { return kEffectName; }
+
   private:
     std::shared_ptr<EnvReverbSwContext> mContext;
-    /* capabilities */
-    const Reverb::Capability kCapability;
-    /* Effect descriptor */
-    const Descriptor kDescriptor = {
-            .common = {.id = {.type = kEnvReverbTypeUUID,
-                              .uuid = kEnvReverbSwImplUUID,
-                              .proxy = std::nullopt},
-                       .flags = {.type = Flags::Type::INSERT,
-                                 .insert = Flags::Insert::FIRST,
-                                 .volume = Flags::Volume::CTRL},
-                       .name = "EnvReverbSw",
-                       .implementor = "The Android Open Source Project"},
-            .capability = Capability::make<Capability::reverb>(kCapability)};
-
     /* parameters */
-    Reverb mSpecificParam;
+    EnvironmentalReverb mSpecificParam;
 };
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/equalizer/EqualizerSw.cpp b/audio/aidl/default/equalizer/EqualizerSw.cpp
index d61ef97..984b943 100644
--- a/audio/aidl/default/equalizer/EqualizerSw.cpp
+++ b/audio/aidl/default/equalizer/EqualizerSw.cpp
@@ -25,6 +25,7 @@
 
 #include "EqualizerSw.h"
 
+using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::EqualizerSw;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::kEqualizerSwImplUUID;
@@ -47,20 +48,41 @@
     }
 }
 
-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) {
-        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
-                   << " in state: " << toString(state) << ", status: " << status.getDescription();
-        return EX_ILLEGAL_STATE;
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kEqualizerSwImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
     }
-    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+    *_aidl_return = EqualizerSw::kDesc;
     return EX_NONE;
 }
 
 namespace aidl::android::hardware::audio::effect {
 
+const std::string EqualizerSw::kEffectName = "EqualizerSw";
+const std::vector<Equalizer::BandFrequency> EqualizerSw::kBandFrequency = {{0, 30000, 120000},
+                                                                           {1, 120001, 460000},
+                                                                           {2, 460001, 1800000},
+                                                                           {3, 1800001, 7000000},
+                                                                           {4, 7000001, 20000000}};
+const std::vector<Equalizer::Preset> EqualizerSw::kPresets = {
+        {0, "Normal"},      {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
+        {5, "Heavy Metal"}, {6, "Hip Hop"},   {7, "Jazz"},  {8, "Pop"},  {9, "Rock"}};
+
+const Equalizer::Capability EqualizerSw::kEqCap = {.bandFrequencies = kBandFrequency,
+                                                   .presets = kPresets};
+
+const Descriptor EqualizerSw::kDesc = {
+        .common = {.id = {.type = kEqualizerTypeUUID,
+                          .uuid = kEqualizerSwImplUUID,
+                          .proxy = kEqualizerProxyUUID},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = EqualizerSw::kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = Capability::make<Capability::equalizer>(EqualizerSw::kEqCap)};
+
 ndk::ScopedAStatus EqualizerSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDesc.toString();
     *_aidl_return = kDesc;
@@ -70,7 +92,6 @@
 ndk::ScopedAStatus EqualizerSw::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::equalizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
-    std::lock_guard lg(mMutex);
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     auto& eqParam = specific.get<Parameter::Specific::equalizer>();
@@ -117,7 +138,6 @@
 
 ndk::ScopedAStatus EqualizerSw::getParameterEqualizer(const Equalizer::Tag& tag,
                                                       Parameter::Specific* specific) {
-    std::lock_guard lg(mMutex);
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     Equalizer eqParam;
@@ -144,9 +164,14 @@
 std::shared_ptr<EffectContext> EqualizerSw::createContext(const Parameter::Common& common) {
     if (mContext) {
         LOG(DEBUG) << __func__ << " context already exist";
-        return mContext;
+    } else {
+        mContext = std::make_shared<EqualizerSwContext>(1 /* statusFmqDepth */, common);
     }
-    mContext = std::make_shared<EqualizerSwContext>(1 /* statusFmqDepth */, common);
+
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> EqualizerSw::getContext() {
     return mContext;
 }
 
@@ -158,13 +183,13 @@
 }
 
 // Processing method running in EffectWorker thread.
-IEffect::Status EqualizerSw::effectProcessImpl(float* in, float* out, int process) {
+IEffect::Status EqualizerSw::effectProcessImpl(float* in, float* out, int samples) {
     // TODO: get data buffer and process.
-    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
-    for (int i = 0; i < process; i++) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    for (int i = 0; i < samples; i++) {
         *out++ = *in++;
     }
-    return {STATUS_OK, process, process};
+    return {STATUS_OK, samples, samples};
 }
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/equalizer/EqualizerSw.h b/audio/aidl/default/equalizer/EqualizerSw.h
index aa4587a..81bcd7a 100644
--- a/audio/aidl/default/equalizer/EqualizerSw.h
+++ b/audio/aidl/default/equalizer/EqualizerSw.h
@@ -80,6 +80,12 @@
 
 class EqualizerSw final : public EffectImpl {
   public:
+    static const std::string kEffectName;
+    static const std::vector<Equalizer::BandFrequency> kBandFrequency;
+    static const std::vector<Equalizer::Preset> kPresets;
+    static const Equalizer::Capability kEqCap;
+    static const Descriptor kDesc;
+
     EqualizerSw() { LOG(DEBUG) << __func__; }
     ~EqualizerSw() {
         cleanUp();
@@ -90,36 +96,18 @@
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
     ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
                                             Parameter::Specific* specific) override;
-    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+
     std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
     RetCode releaseContext() override;
 
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+    std::string getEffectName() override { return kEffectName; }
+
   private:
-    std::shared_ptr<EqualizerSwContext> mContext;
-    /* capabilities */
-    const std::vector<Equalizer::BandFrequency> mBandFrequency = {{0, 30000, 120000},
-                                                                  {1, 120001, 460000},
-                                                                  {2, 460001, 1800000},
-                                                                  {3, 1800001, 7000000},
-                                                                  {4, 7000001, 20000000}};
-    // presets supported by the device
-    const std::vector<Equalizer::Preset> mPresets = {
-            {0, "Normal"},      {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
-            {5, "Heavy Metal"}, {6, "Hip Hop"},   {7, "Jazz"},  {8, "Pop"},  {9, "Rock"}};
-
-    const Equalizer::Capability kEqCap = {.bandFrequencies = mBandFrequency, .presets = mPresets};
-    // Effect descriptor.
-    const Descriptor kDesc = {.common = {.id = {.type = kEqualizerTypeUUID,
-                                                .uuid = kEqualizerSwImplUUID,
-                                                .proxy = kEqualizerProxyUUID},
-                                         .flags = {.type = Flags::Type::INSERT,
-                                                   .insert = Flags::Insert::FIRST,
-                                                   .volume = Flags::Volume::CTRL},
-                                         .name = "EqualizerSw",
-                                         .implementor = "The Android Open Source Project"},
-                              .capability = Capability::make<Capability::equalizer>(kEqCap)};
-
     ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
                                              Parameter::Specific* specific);
+    std::shared_ptr<EqualizerSwContext> mContext;
 };
+
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
index fd5ea34..8004631 100644
--- a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
+++ b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
@@ -25,6 +25,7 @@
 
 #include "HapticGeneratorSw.h"
 
+using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::HapticGeneratorSw;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::kHapticGeneratorSwImplUUID;
@@ -47,23 +48,33 @@
     }
 }
 
-extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
-    if (!instanceSp) {
-        return EX_NONE;
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kHapticGeneratorSwImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
     }
-    State state;
-    ndk::ScopedAStatus status = instanceSp->getState(&state);
-    if (!status.isOk() || State::INIT != state) {
-        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
-                   << " in state: " << toString(state) << ", status: " << status.getDescription();
-        return EX_ILLEGAL_STATE;
-    }
-    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+    *_aidl_return = HapticGeneratorSw::kDescriptor;
     return EX_NONE;
 }
 
 namespace aidl::android::hardware::audio::effect {
 
+const std::string HapticGeneratorSw::kEffectName = "HapticGeneratorSw";
+/* capabilities */
+const HapticGenerator::Capability HapticGeneratorSw::kCapability;
+/* Effect descriptor */
+const Descriptor HapticGeneratorSw::kDescriptor = {
+        .common = {.id = {.type = kHapticGeneratorTypeUUID,
+                          .uuid = kHapticGeneratorSwImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = HapticGeneratorSw::kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability =
+                Capability::make<Capability::hapticGenerator>(HapticGeneratorSw::kCapability)};
+
 ndk::ScopedAStatus HapticGeneratorSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
     *_aidl_return = kDescriptor;
@@ -73,9 +84,6 @@
 ndk::ScopedAStatus HapticGeneratorSw::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::hapticGenerator != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
-    std::lock_guard lg(mMutex);
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
-
     mSpecificParam = specific.get<Parameter::Specific::hapticGenerator>();
     LOG(DEBUG) << __func__ << " success with: " << specific.toString();
     return ndk::ScopedAStatus::ok();
@@ -92,9 +100,14 @@
 std::shared_ptr<EffectContext> HapticGeneratorSw::createContext(const Parameter::Common& common) {
     if (mContext) {
         LOG(DEBUG) << __func__ << " context already exist";
-        return mContext;
+    } else {
+        mContext = std::make_shared<HapticGeneratorSwContext>(1 /* statusFmqDepth */, common);
     }
-    mContext = std::make_shared<HapticGeneratorSwContext>(1 /* statusFmqDepth */, common);
+
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> HapticGeneratorSw::getContext() {
     return mContext;
 }
 
@@ -106,13 +119,13 @@
 }
 
 // Processing method running in EffectWorker thread.
-IEffect::Status HapticGeneratorSw::effectProcessImpl(float* in, float* out, int process) {
+IEffect::Status HapticGeneratorSw::effectProcessImpl(float* in, float* out, int samples) {
     // TODO: get data buffer and process.
-    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
-    for (int i = 0; i < process; i++) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    for (int i = 0; i < samples; i++) {
         *out++ = *in++;
     }
-    return {STATUS_OK, process, process};
+    return {STATUS_OK, samples, samples};
 }
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
index 518aa87..bf01bfb 100644
--- a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
+++ b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
@@ -37,6 +37,9 @@
 
 class HapticGeneratorSw final : public EffectImpl {
   public:
+    static const std::string kEffectName;
+    static const HapticGenerator::Capability kCapability;
+    static const Descriptor kDescriptor;
     HapticGeneratorSw() { LOG(DEBUG) << __func__; }
     ~HapticGeneratorSw() {
         cleanUp();
@@ -47,26 +50,16 @@
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
     ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
                                             Parameter::Specific* specific) override;
-    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+
     std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
     RetCode releaseContext() override;
 
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+    std::string getEffectName() override { return kEffectName; }
+
   private:
     std::shared_ptr<HapticGeneratorSwContext> mContext;
-    /* capabilities */
-    const HapticGenerator::Capability kCapability;
-    /* Effect descriptor */
-    const Descriptor kDescriptor = {
-            .common = {.id = {.type = kHapticGeneratorTypeUUID,
-                              .uuid = kHapticGeneratorSwImplUUID,
-                              .proxy = std::nullopt},
-                       .flags = {.type = Flags::Type::INSERT,
-                                 .insert = Flags::Insert::FIRST,
-                                 .volume = Flags::Volume::CTRL},
-                       .name = "HapticGeneratorSw",
-                       .implementor = "The Android Open Source Project"},
-            .capability = Capability::make<Capability::hapticGenerator>(kCapability)};
-
     /* parameters */
     HapticGenerator mSpecificParam;
 };
diff --git a/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h b/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h
new file mode 100644
index 0000000..47918f0
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
+#include <android_audio_policy_configuration.h>
+#include <android_audio_policy_configuration_enums.h>
+
+#include "core-impl/XmlConverter.h"
+
+namespace aidl::android::hardware::audio::core::internal {
+
+class AudioPolicyConfigXmlConverter {
+  public:
+    explicit AudioPolicyConfigXmlConverter(const std::string& configFilePath)
+        : mConverter(configFilePath, &::android::audio::policy::configuration::read) {}
+
+    std::string getError() const { return mConverter.getError(); }
+    ::android::status_t getStatus() const { return mConverter.getStatus(); }
+
+    const ::aidl::android::media::audio::common::AudioHalEngineConfig& getAidlEngineConfig();
+
+  private:
+    const std::optional<::android::audio::policy::configuration::AudioPolicyConfiguration>&
+    getXsdcConfig() const {
+        return mConverter.getXsdcConfig();
+    }
+    void addVolumeGroupstoEngineConfig();
+    void mapStreamToVolumeCurve(
+            const ::android::audio::policy::configuration::Volume& xsdcVolumeCurve);
+    void mapStreamsToVolumeCurves();
+    void parseVolumes();
+    ::aidl::android::media::audio::common::AudioHalVolumeCurve::CurvePoint convertCurvePointToAidl(
+            const std::string& xsdcCurvePoint);
+
+    ::aidl::android::media::audio::common::AudioHalVolumeCurve convertVolumeCurveToAidl(
+            const ::android::audio::policy::configuration::Volume& xsdcVolumeCurve);
+
+    ::aidl::android::media::audio::common::AudioHalEngineConfig mAidlEngineConfig;
+    XmlConverter<::android::audio::policy::configuration::AudioPolicyConfiguration> mConverter;
+    std::unordered_map<std::string, ::android::audio::policy::configuration::Reference>
+            mVolumesReferenceMap;
+    std::unordered_map<::android::audio::policy::configuration::AudioStreamType,
+                       std::vector<::aidl::android::media::audio::common::AudioHalVolumeCurve>>
+            mStreamToVolumeCurvesMap;
+};
+
+}  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/include/core-impl/Config.h b/audio/aidl/default/include/core-impl/Config.h
index 4555efd..96a6cb9 100644
--- a/audio/aidl/default/include/core-impl/Config.h
+++ b/audio/aidl/default/include/core-impl/Config.h
@@ -17,11 +17,22 @@
 #pragma once
 
 #include <aidl/android/hardware/audio/core/BnConfig.h>
+#include <system/audio_config.h>
+
+#include "AudioPolicyConfigXmlConverter.h"
+#include "EngineConfigXmlConverter.h"
 
 namespace aidl::android::hardware::audio::core {
+static const std::string kEngineConfigFileName = "audio_policy_engine_configuration.xml";
 
 class Config : public BnConfig {
     ndk::ScopedAStatus getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) override;
+    ndk::ScopedAStatus getEngineConfig(
+            aidl::android::media::audio::common::AudioHalEngineConfig* _aidl_return) override;
+    internal::AudioPolicyConfigXmlConverter mAudioPolicyConverter{
+            ::android::audio_get_audio_policy_config_file()};
+    internal::EngineConfigXmlConverter mEngConfigConverter{
+            ::android::audio_find_readable_configuration_file(kEngineConfigFileName.c_str())};
 };
 
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Configuration.h b/audio/aidl/default/include/core-impl/Configuration.h
index 95adcd7..3b4c494 100644
--- a/audio/aidl/default/include/core-impl/Configuration.h
+++ b/audio/aidl/default/include/core-impl/Configuration.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <map>
+#include <memory>
 #include <vector>
 
 #include <aidl/android/hardware/audio/core/AudioPatch.h>
@@ -41,6 +42,7 @@
     int32_t nextPatchId = 1;
 };
 
-Configuration& getNullPrimaryConfiguration();
+std::unique_ptr<Configuration> getPrimaryConfiguration();
+std::unique_ptr<Configuration> getRSubmixConfiguration();
 
 }  // 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
new file mode 100644
index 0000000..b34441d
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <unordered_map>
+
+#include <utils/Errors.h>
+
+#include <android_audio_policy_engine_configuration.h>
+#include <android_audio_policy_engine_configuration_enums.h>
+
+#include "core-impl/XmlConverter.h"
+
+namespace aidl::android::hardware::audio::core::internal {
+
+class EngineConfigXmlConverter {
+  public:
+    explicit EngineConfigXmlConverter(const std::string& configFilePath)
+        : mConverter(configFilePath, &::android::audio::policy::engine::configuration::read) {
+        if (mConverter.getXsdcConfig()) {
+            init();
+        }
+    }
+
+    std::string getError() const { return mConverter.getError(); }
+    ::android::status_t getStatus() const { return mConverter.getStatus(); }
+
+    ::aidl::android::media::audio::common::AudioHalEngineConfig& getAidlEngineConfig();
+
+  private:
+    const std::optional<::android::audio::policy::engine::configuration::Configuration>&
+    getXsdcConfig() {
+        return mConverter.getXsdcConfig();
+    }
+    void init();
+    void initProductStrategyMap();
+    ::aidl::android::media::audio::common::AudioAttributes convertAudioAttributesToAidl(
+            const ::android::audio::policy::engine::configuration::AttributesType&
+                    xsdcAudioAttributes);
+    ::aidl::android::media::audio::common::AudioHalAttributesGroup convertAttributesGroupToAidl(
+            const ::android::audio::policy::engine::configuration::AttributesGroup&
+                    xsdcAttributesGroup);
+    ::aidl::android::media::audio::common::AudioHalCapCriterion convertCapCriterionToAidl(
+            const ::android::audio::policy::engine::configuration::CriterionType& xsdcCriterion);
+    ::aidl::android::media::audio::common::AudioHalCapCriterionType convertCapCriterionTypeToAidl(
+            const ::android::audio::policy::engine::configuration::CriterionTypeType&
+                    xsdcCriterionType);
+    std::string convertCriterionTypeValueToAidl(
+            const ::android::audio::policy::engine::configuration::ValueType&
+                    xsdcCriterionTypeValue);
+    ::aidl::android::media::audio::common::AudioHalVolumeCurve::CurvePoint convertCurvePointToAidl(
+            const std::string& xsdcCurvePoint);
+    ::aidl::android::media::audio::common::AudioHalProductStrategy convertProductStrategyToAidl(
+            const ::android::audio::policy::engine::configuration::ProductStrategies::
+                    ProductStrategy& xsdcProductStrategy);
+    int convertProductStrategyNameToAidl(const std::string& xsdcProductStrategyName);
+    ::aidl::android::media::audio::common::AudioHalVolumeCurve convertVolumeCurveToAidl(
+            const ::android::audio::policy::engine::configuration::Volume& xsdcVolumeCurve);
+    ::aidl::android::media::audio::common::AudioHalVolumeGroup convertVolumeGroupToAidl(
+            const ::android::audio::policy::engine::configuration::VolumeGroupsType::VolumeGroup&
+                    xsdcVolumeGroup);
+
+    ::aidl::android::media::audio::common::AudioHalEngineConfig mAidlEngineConfig;
+    XmlConverter<::android::audio::policy::engine::configuration::Configuration> mConverter;
+    std::unordered_map<std::string,
+                       ::android::audio::policy::engine::configuration::AttributesRefType>
+            mAttributesReferenceMap;
+    std::unordered_map<std::string, ::android::audio::policy::engine::configuration::VolumeRef>
+            mVolumesReferenceMap;
+    std::unordered_map<std::string, int> mProductStrategyMap;
+    int mNextVendorStrategy = ::aidl::android::media::audio::common::AudioHalProductStrategy::
+            VENDOR_STRATEGY_ID_START;
+    std::optional<int> mDefaultProductStrategyId;
+};
+
+}  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 3509327..52fb54c 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -31,6 +31,9 @@
   public:
     // This value is used for all AudioPatches and reported by all streams.
     static constexpr int32_t kLatencyMs = 10;
+    enum Type : int { DEFAULT, R_SUBMIX };
+
+    explicit Module(Type type) : mType(type) {}
 
   private:
     ndk::ScopedAStatus setModuleDebug(
@@ -105,6 +108,7 @@
     // The maximum stream buffer size is 1 GiB = 2 ** 30 bytes;
     static constexpr int32_t kMaximumStreamBufferSizeBytes = 1 << 30;
 
+    const Type mType;
     std::unique_ptr<internal::Configuration> mConfig;
     ModuleDebug mDebug;
     // Since it is required to return the same instance of the ITelephony, even
diff --git a/audio/aidl/default/include/core-impl/XmlConverter.h b/audio/aidl/default/include/core-impl/XmlConverter.h
new file mode 100644
index 0000000..ec23edb
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/XmlConverter.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <optional>
+#include <string>
+#include <unordered_map>
+
+#include <system/audio_config.h>
+#include <utils/Errors.h>
+
+namespace aidl::android::hardware::audio::core::internal {
+
+template <typename T>
+class XmlConverter {
+  public:
+    XmlConverter(const std::string& configFilePath,
+                 std::function<std::optional<T>(const char*)> readXmlConfig)
+        : XmlConverter(configFilePath,
+                       ::android::audio_is_readable_configuration_file(configFilePath.c_str()),
+                       readXmlConfig) {}
+
+    const ::android::status_t& getStatus() const { return mStatus; }
+
+    const std::string& getError() const { return mErrorMessage; }
+
+    const std::optional<T>& getXsdcConfig() const { return mXsdcConfig; }
+
+  private:
+    XmlConverter(const std::string& configFilePath, const bool& isReadableConfigFile,
+                 const std::function<std::optional<T>(const char*)>& readXmlConfig)
+        : mXsdcConfig{isReadableConfigFile ? readXmlConfig(configFilePath.c_str()) : std::nullopt},
+          mStatus(mXsdcConfig ? ::android::OK : ::android::NO_INIT),
+          mErrorMessage(generateError(configFilePath, isReadableConfigFile, mStatus)) {}
+
+    static std::string generateError(const std::string& configFilePath,
+                                     const bool& isReadableConfigFile,
+                                     const ::android::status_t& status) {
+        std::string errorMessage;
+        if (status != ::android::OK) {
+            if (!isReadableConfigFile) {
+                errorMessage = "Could not read requested config file:" + configFilePath;
+            } else {
+                errorMessage = "Invalid config file: " + configFilePath;
+            }
+        }
+        return errorMessage;
+    }
+
+    const std::optional<T> mXsdcConfig;
+    const ::android::status_t mStatus;
+    const std::string mErrorMessage;
+};
+
+/**
+ * Converts a vector of an xsd wrapper type to a flat vector of the
+ * corresponding AIDL type.
+ *
+ * Wrapper types are used in order to have well-formed xIncludes. In the
+ * example below, Modules is the wrapper type for Module.
+ *     <Modules>
+ *         <Module> ... </Module>
+ *         <Module> ... </Module>
+ *     </Modules>
+ */
+template <typename W, typename X, typename A>
+static std::vector<A> convertWrappedCollectionToAidl(
+        const std::vector<W>& xsdcWrapperTypeVec,
+        std::function<const std::vector<X>&(const W&)> getInnerTypeVec,
+        std::function<A(const X&)> convertToAidl) {
+    std::vector<A> resultAidlTypeVec;
+    if (!xsdcWrapperTypeVec.empty()) {
+        /*
+         * xsdcWrapperTypeVec likely only contains one element; that is, it's
+         * likely that all the inner types that we need to convert are inside of
+         * xsdcWrapperTypeVec[0].
+         */
+        resultAidlTypeVec.reserve(getInnerTypeVec(xsdcWrapperTypeVec[0]).size());
+        for (const W& xsdcWrapperType : xsdcWrapperTypeVec) {
+            std::transform(getInnerTypeVec(xsdcWrapperType).begin(),
+                           getInnerTypeVec(xsdcWrapperType).end(),
+                           std::back_inserter(resultAidlTypeVec), convertToAidl);
+        }
+    }
+    return resultAidlTypeVec;
+}
+
+template <typename X, typename A>
+static std::vector<A> convertCollectionToAidl(const std::vector<X>& xsdcTypeVec,
+                                              std::function<A(const X&)> convertToAidl) {
+    std::vector<A> resultAidlTypeVec;
+    resultAidlTypeVec.reserve(xsdcTypeVec.size());
+    std::transform(xsdcTypeVec.begin(), xsdcTypeVec.end(), std::back_inserter(resultAidlTypeVec),
+                   convertToAidl);
+    return resultAidlTypeVec;
+}
+
+/**
+ * Generates a map of xsd references, keyed by reference name, given a
+ * vector of wrapper types for the reference.
+ *
+ * Wrapper types are used in order to have well-formed xIncludes. In the
+ * example below, Wrapper is the wrapper type for Reference.
+ *     <Wrapper>
+ *         <Reference> ... </Reference>
+ *         <Reference> ... </Reference>
+ *     </Wrapper>
+ */
+template <typename W, typename R>
+static std::unordered_map<std::string, R> generateReferenceMap(
+        const std::vector<W>& xsdcWrapperTypeVec) {
+    std::unordered_map<std::string, R> resultMap;
+    if (!xsdcWrapperTypeVec.empty()) {
+        /*
+         * xsdcWrapperTypeVec likely only contains one element; that is, it's
+         * likely that all the inner types that we need to convert are inside of
+         * xsdcWrapperTypeVec[0].
+         */
+        resultMap.reserve(xsdcWrapperTypeVec[0].getReference().size());
+        for (const W& xsdcWrapperType : xsdcWrapperTypeVec) {
+            for (const R& xsdcReference : xsdcWrapperType.getReference()) {
+                resultMap.insert({xsdcReference.getName(), xsdcReference});
+            }
+        }
+    }
+    return resultMap;
+}
+}  // 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 f608e12..95645d5 100644
--- a/audio/aidl/default/include/effect-impl/EffectContext.h
+++ b/audio/aidl/default/include/effect-impl/EffectContext.h
@@ -16,16 +16,13 @@
 
 #pragma once
 #include <Utils.h>
-#include <android-base/logging.h>
-#include <utils/Log.h>
-#include <cstddef>
-#include <cstdint>
 #include <memory>
-#include <utility>
 #include <vector>
 
-#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <android-base/logging.h>
 #include <fmq/AidlMessageQueue.h>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
 #include "EffectTypes.h"
 
 namespace aidl::android::hardware::audio::effect {
@@ -74,13 +71,10 @@
     std::shared_ptr<DataMQ> getOutputDataFmq() { return mOutputMQ; }
 
     float* getWorkBuffer() { return static_cast<float*>(mWorkBuffer.data()); }
-    // TODO: update with actual available size
-    size_t availableToRead() { return mWorkBuffer.capacity(); }
-    size_t availableToWrite() { return mWorkBuffer.capacity(); }
 
     // reset buffer status by abandon all data and status in FMQ
     void resetBuffer() {
-        auto buffer = getWorkBuffer();
+        auto buffer = static_cast<float*>(mWorkBuffer.data());
         std::vector<IEffect::Status> status(mStatusMQ->availableToRead());
         mInputMQ->read(buffer, mInputMQ->availableToRead());
         mOutputMQ->read(buffer, mOutputMQ->availableToRead());
@@ -89,9 +83,9 @@
 
     void dupeFmq(IEffect::OpenEffectReturn* effectRet) {
         if (effectRet) {
-            effectRet->statusMQ = getStatusFmq()->dupeDesc();
-            effectRet->inputDataMQ = getInputDataFmq()->dupeDesc();
-            effectRet->outputDataMQ = getOutputDataFmq()->dupeDesc();
+            effectRet->statusMQ = mStatusMQ->dupeDesc();
+            effectRet->inputDataMQ = mInputMQ->dupeDesc();
+            effectRet->outputDataMQ = mOutputMQ->dupeDesc();
         }
     }
     size_t getInputFrameSize() { return mInputFrameSize; }
@@ -138,7 +132,8 @@
   protected:
     // common parameters
     int mSessionId = INVALID_AUDIO_SESSION_ID;
-    size_t mInputFrameSize, mOutputFrameSize;
+    size_t mInputFrameSize;
+    size_t mOutputFrameSize;
     Parameter::Common mCommon;
     aidl::android::media::audio::common::AudioDeviceDescription mOutputDevice;
     aidl::android::media::audio::common::AudioMode mMode;
diff --git a/audio/aidl/default/include/effect-impl/EffectImpl.h b/audio/aidl/default/include/effect-impl/EffectImpl.h
index d9825da..e7d081f 100644
--- a/audio/aidl/default/include/effect-impl/EffectImpl.h
+++ b/audio/aidl/default/include/effect-impl/EffectImpl.h
@@ -15,45 +15,38 @@
  */
 
 #pragma once
-#include <aidl/android/hardware/audio/effect/BnEffect.h>
-#include <fmq/AidlMessageQueue.h>
 #include <cstdlib>
 #include <memory>
-#include <mutex>
 
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "EffectContext.h"
+#include "EffectThread.h"
 #include "EffectTypes.h"
 #include "effect-impl/EffectContext.h"
+#include "effect-impl/EffectThread.h"
 #include "effect-impl/EffectTypes.h"
-#include "effect-impl/EffectWorker.h"
+
+extern "C" binder_exception_t destroyEffect(
+        const std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>& instanceSp);
 
 namespace aidl::android::hardware::audio::effect {
 
-class EffectImpl : public BnEffect, public EffectWorker {
+class EffectImpl : public BnEffect, public EffectThread {
   public:
     EffectImpl() = default;
     virtual ~EffectImpl() = default;
 
-    /**
-     * Each effect implementation CAN override these methods if necessary
-     * If you would like implement IEffect::open completely, override EffectImpl::open(), if you
-     * want to keep most of EffectImpl logic but have a little customize, try override openImpl().
-     * openImpl() will be called at the beginning of EffectImpl::open() without lock protection.
-     *
-     * Same for closeImpl().
-     */
     virtual ndk::ScopedAStatus open(const Parameter::Common& common,
                                     const std::optional<Parameter::Specific>& specific,
                                     OpenEffectReturn* ret) override;
     virtual ndk::ScopedAStatus close() override;
     virtual ndk::ScopedAStatus command(CommandId id) override;
-    virtual ndk::ScopedAStatus commandStart() { return ndk::ScopedAStatus::ok(); }
-    virtual ndk::ScopedAStatus commandStop() { return ndk::ScopedAStatus::ok(); }
-    virtual ndk::ScopedAStatus commandReset() { return ndk::ScopedAStatus::ok(); }
 
     virtual ndk::ScopedAStatus getState(State* state) override;
     virtual ndk::ScopedAStatus setParameter(const Parameter& param) override;
     virtual ndk::ScopedAStatus getParameter(const Parameter::Id& id, Parameter* param) override;
-    virtual IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
 
     virtual ndk::ScopedAStatus setParameterCommon(const Parameter& param);
     virtual ndk::ScopedAStatus getParameterCommon(const Parameter::Tag& tag, Parameter* param);
@@ -63,21 +56,32 @@
     virtual ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) = 0;
     virtual ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
                                                     Parameter::Specific* specific) = 0;
+
+    virtual std::string getEffectName() = 0;
+    virtual IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+
+    /**
+     * Effect context methods must be implemented by each effect.
+     * Each effect can derive from EffectContext and define its own context, but must upcast to
+     * EffectContext for EffectImpl to use.
+     */
     virtual std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) = 0;
+    virtual std::shared_ptr<EffectContext> getContext() = 0;
     virtual RetCode releaseContext() = 0;
 
   protected:
-    /*
-     * Lock is required if effectProcessImpl (which is running in an independent thread) needs to
-     * access state and parameters.
-     */
-    std::mutex mMutex;
-    State mState GUARDED_BY(mMutex) = State::INIT;
+    State mState = State::INIT;
 
     IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
     void cleanUp();
 
-  private:
-    std::shared_ptr<EffectContext> mContext GUARDED_BY(mMutex);
+    /**
+     * Optional CommandId handling methods for effects to override.
+     * For CommandId::START, EffectImpl call commandImpl before starting the EffectThread
+     * processing.
+     * For CommandId::STOP and CommandId::RESET, EffectImpl call commandImpl after stop the
+     * EffectThread processing.
+     */
+    virtual ndk::ScopedAStatus commandImpl(CommandId id);
 };
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectThread.h b/audio/aidl/default/include/effect-impl/EffectThread.h
index 09a0000..4b6cecd 100644
--- a/audio/aidl/default/include/effect-impl/EffectThread.h
+++ b/audio/aidl/default/include/effect-impl/EffectThread.h
@@ -22,6 +22,7 @@
 #include <android-base/thread_annotations.h>
 #include <system/thread_defs.h>
 
+#include "effect-impl/EffectContext.h"
 #include "effect-impl/EffectTypes.h"
 
 namespace aidl::android::hardware::audio::effect {
@@ -33,7 +34,7 @@
     virtual ~EffectThread();
 
     // called by effect implementation.
-    RetCode createThread(const std::string& name,
+    RetCode createThread(std::shared_ptr<EffectContext> context, const std::string& name,
                          const int priority = ANDROID_PRIORITY_URGENT_AUDIO);
     RetCode destroyThread();
     RetCode startThread();
@@ -42,15 +43,43 @@
     // Will call process() in a loop if the thread is running.
     void threadLoop();
 
-    // User of EffectThread must implement the effect processing logic in this method.
-    virtual void process() = 0;
-    const int MAX_TASK_COMM_LEN = 15;
+    /**
+     * @brief effectProcessImpl is running in worker thread which created in EffectThread.
+     *
+     * Effect implementation should think about concurrency in the implementation if necessary.
+     * Parameter setting usually implemented in context (derived from EffectContext), and some
+     * parameter maybe used in the processing, then effect implementation should consider using a
+     * mutex to protect these parameter.
+     *
+     * EffectThread will make sure effectProcessImpl only be called after startThread() successful
+     * and before stopThread() successful.
+     *
+     * @param in address of input float buffer.
+     * @param out address of output float buffer.
+     * @param samples number of samples to process.
+     * @return IEffect::Status
+     */
+    virtual IEffect::Status effectProcessImpl(float* in, float* out, int samples) = 0;
+
+    /**
+     * The default EffectThread::process() implementation doesn't need to lock. It will only
+     * access the FMQ and mWorkBuffer in  EffectContext, since they will only be changed in
+     * EffectImpl IEffect::open() (in this case EffectThread just created and not running yet) and
+     * IEffect::command(CommandId::RESET) (in this case EffectThread already stopped).
+     *
+     * process() call effectProcessImpl for effect processing, and because effectProcessImpl is
+     * implemented by effects, process() must not hold lock before call into effectProcessImpl to
+     * avoid deadlock.
+     */
+    virtual void process();
 
   private:
-    std::mutex mMutex;
+    const int kMaxTaskNameLen = 15;
+    std::mutex mThreadMutex;
     std::condition_variable mCv;
-    bool mExit GUARDED_BY(mMutex) = false;
-    bool mStop GUARDED_BY(mMutex) = true;
+    bool mExit GUARDED_BY(mThreadMutex) = false;
+    bool mStop GUARDED_BY(mThreadMutex) = true;
+    std::shared_ptr<EffectContext> mThreadContext GUARDED_BY(mThreadMutex);
     std::thread mThread;
     int mPriority;
     std::string mName;
diff --git a/audio/aidl/default/include/effect-impl/EffectTypes.h b/audio/aidl/default/include/effect-impl/EffectTypes.h
index fc6a01d..58c8672 100644
--- a/audio/aidl/default/include/effect-impl/EffectTypes.h
+++ b/audio/aidl/default/include/effect-impl/EffectTypes.h
@@ -26,10 +26,14 @@
         std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>*);
 typedef binder_exception_t (*EffectDestroyFunctor)(
         const std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>&);
+typedef binder_exception_t (*EffectQueryFunctor)(
+        const ::aidl::android::media::audio::common::AudioUuid*,
+        aidl::android::hardware::audio::effect::Descriptor*);
 
 struct effect_dl_interface_s {
     EffectCreateFunctor createEffectFunc;
     EffectDestroyFunctor destroyEffectFunc;
+    EffectQueryFunctor queryEffectFunc;
 };
 
 namespace aidl::android::hardware::audio::effect {
@@ -102,6 +106,15 @@
         }                                                                                        \
     } while (0)
 
+#define RETURN_IF_BINDER_EXCEPTION(functor)                                 \
+    {                                                                       \
+        binder_exception_t exception = functor;                             \
+        if (EX_NONE != exception) {                                         \
+            LOG(ERROR) << #functor << ":  failed with error " << exception; \
+            return ndk::ScopedAStatus::fromExceptionCode(exception);        \
+        }                                                                   \
+    }
+
 static inline bool stringToUuid(const char* str,
                                 ::aidl::android::media::audio::common::AudioUuid* uuid) {
     RETURN_VALUE_IF(!uuid || !str, false, "nullPtr");
diff --git a/audio/aidl/default/include/effect-impl/EffectWorker.h b/audio/aidl/default/include/effect-impl/EffectWorker.h
index 6a78eab..b456817 100644
--- a/audio/aidl/default/include/effect-impl/EffectWorker.h
+++ b/audio/aidl/default/include/effect-impl/EffectWorker.h
@@ -63,7 +63,7 @@
 
     // must implement by each effect implementation
     // TODO: consider if this interface need adjustment to handle in-place processing
-    virtual IEffect::Status effectProcessImpl(float* in, float* out, int processSamples) = 0;
+    virtual IEffect::Status effectProcessImpl(float* in, float* out, int samples) = 0;
 
   private:
     // make sure the context only set once.
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
index 7edace0..5903276 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
@@ -20,6 +20,7 @@
 #include <map>
 #include <optional>
 #include <set>
+#include <tuple>
 #include <vector>
 
 #include <aidl/android/hardware/audio/effect/BnFactory.h>
@@ -37,14 +38,14 @@
      * @param in_type Type UUID.
      * @param in_instance Instance UUID.
      * @param in_proxy Proxy UUID.
-     * @param out_descriptor List of identities .
+     * @param out_descriptor List of Descriptors.
      * @return ndk::ScopedAStatus
      */
     ndk::ScopedAStatus queryEffects(
             const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_type,
             const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_instance,
             const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_proxy,
-            std::vector<Descriptor::Identity>* out_descriptor) override;
+            std::vector<Descriptor>* out_descriptor) override;
 
     /**
      * @brief Query list of defined processing, with the optional filter by AudioStreamType
@@ -82,12 +83,19 @@
     const EffectConfig mConfig;
     ~Factory();
     // Set of effect descriptors supported by the devices.
+    std::set<Descriptor> mDescSet;
     std::set<Descriptor::Identity> mIdentitySet;
 
-    std::map<aidl::android::media::audio::common::AudioUuid /* implementationUUID */,
-             std::pair<std::unique_ptr<void, std::function<void(void*)>> /* dlHandle */,
-                       std::unique_ptr<struct effect_dl_interface_s>>>
-            mEffectLibMap;
+    static constexpr int kMapEntryHandleIndex = 0;
+    static constexpr int kMapEntryInterfaceIndex = 1;
+    static constexpr int kMapEntryLibNameIndex = 2;
+    typedef std::tuple<std::unique_ptr<void, std::function<void(void*)>> /* dlHandle */,
+                       std::unique_ptr<struct effect_dl_interface_s> /* interfaces */,
+                       std::string /* library name */>
+            DlEntry;
+
+    std::map<aidl::android::media::audio::common::AudioUuid /* implUUID */, DlEntry> mEffectLibMap;
+
     std::map<std::weak_ptr<IEffect>, aidl::android::media::audio::common::AudioUuid,
              std::owner_less<>>
             mEffectUuidMap;
@@ -101,6 +109,8 @@
             const ::aidl::android::media::audio::common::AudioUuid& typeUuid,
             const std::optional<::aidl::android::media::audio::common::AudioUuid> proxyUuid);
     void loadEffectLibs();
+    /* Get effect_dl_interface_s from library handle */
+    void getDlSyms(DlEntry& entry);
 };
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.cpp b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.cpp
index 9d2b978..da02076 100644
--- a/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.cpp
+++ b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.cpp
@@ -25,6 +25,7 @@
 
 #include "LoudnessEnhancerSw.h"
 
+using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::kLoudnessEnhancerSwImplUUID;
 using aidl::android::hardware::audio::effect::LoudnessEnhancerSw;
@@ -47,23 +48,28 @@
     }
 }
 
-extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
-    if (!instanceSp) {
-        return EX_NONE;
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kLoudnessEnhancerSwImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
     }
-    State state;
-    ndk::ScopedAStatus status = instanceSp->getState(&state);
-    if (!status.isOk() || State::INIT != state) {
-        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
-                   << " in state: " << toString(state) << ", status: " << status.getDescription();
-        return EX_ILLEGAL_STATE;
-    }
-    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+    *_aidl_return = LoudnessEnhancerSw::kDescriptor;
     return EX_NONE;
 }
 
 namespace aidl::android::hardware::audio::effect {
 
+const std::string LoudnessEnhancerSw::kEffectName = "LoudnessEnhancerSw";
+const Descriptor LoudnessEnhancerSw::kDescriptor = {
+        .common = {.id = {.type = kLoudnessEnhancerTypeUUID,
+                          .uuid = kLoudnessEnhancerSwImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = LoudnessEnhancerSw::kEffectName,
+                   .implementor = "The Android Open Source Project"}};
+
 ndk::ScopedAStatus LoudnessEnhancerSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
     *_aidl_return = kDescriptor;
@@ -73,7 +79,6 @@
 ndk::ScopedAStatus LoudnessEnhancerSw::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::loudnessEnhancer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
-    std::lock_guard lg(mMutex);
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     auto& leParam = specific.get<Parameter::Specific::loudnessEnhancer>();
@@ -113,7 +118,6 @@
 
 ndk::ScopedAStatus LoudnessEnhancerSw::getParameterLoudnessEnhancer(
         const LoudnessEnhancer::Tag& tag, Parameter::Specific* specific) {
-    std::lock_guard lg(mMutex);
     RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     LoudnessEnhancer leParam;
@@ -136,9 +140,14 @@
 std::shared_ptr<EffectContext> LoudnessEnhancerSw::createContext(const Parameter::Common& common) {
     if (mContext) {
         LOG(DEBUG) << __func__ << " context already exist";
-        return mContext;
+    } else {
+        mContext = std::make_shared<LoudnessEnhancerSwContext>(1 /* statusFmqDepth */, common);
     }
-    mContext = std::make_shared<LoudnessEnhancerSwContext>(1 /* statusFmqDepth */, common);
+
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> LoudnessEnhancerSw::getContext() {
     return mContext;
 }
 
@@ -150,13 +159,13 @@
 }
 
 // Processing method running in EffectWorker thread.
-IEffect::Status LoudnessEnhancerSw::effectProcessImpl(float* in, float* out, int process) {
+IEffect::Status LoudnessEnhancerSw::effectProcessImpl(float* in, float* out, int samples) {
     // TODO: get data buffer and process.
-    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
-    for (int i = 0; i < process; i++) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    for (int i = 0; i < samples; i++) {
         *out++ = *in++;
     }
-    return {STATUS_OK, process, process};
+    return {STATUS_OK, samples, samples};
 }
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h
index 856bf0b..5da70c7 100644
--- a/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h
+++ b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h
@@ -46,6 +46,9 @@
 
 class LoudnessEnhancerSw final : public EffectImpl {
   public:
+    static const std::string kEffectName;
+    static const LoudnessEnhancer::Capability kCapability;
+    static const Descriptor kDescriptor;
     LoudnessEnhancerSw() { LOG(DEBUG) << __func__; }
     ~LoudnessEnhancerSw() {
         cleanUp();
@@ -56,26 +59,16 @@
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
     ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
                                             Parameter::Specific* specific) override;
-    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+
     std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
     RetCode releaseContext() override;
 
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+    std::string getEffectName() override { return kEffectName; }
+
   private:
     std::shared_ptr<LoudnessEnhancerSwContext> mContext;
-    /* capabilities */
-    const LoudnessEnhancer::Capability kCapability;
-    /* Effect descriptor */
-    const Descriptor kDescriptor = {
-            .common = {.id = {.type = kLoudnessEnhancerTypeUUID,
-                              .uuid = kLoudnessEnhancerSwImplUUID,
-                              .proxy = std::nullopt},
-                       .flags = {.type = Flags::Type::INSERT,
-                                 .insert = Flags::Insert::FIRST,
-                                 .volume = Flags::Volume::CTRL},
-                       .name = "LoudnessEnhancerSw",
-                       .implementor = "The Android Open Source Project"},
-            .capability = Capability::make<Capability::loudnessEnhancer>(kCapability)};
-
     ndk::ScopedAStatus getParameterLoudnessEnhancer(const LoudnessEnhancer::Tag& tag,
                                                     Parameter::Specific* specific);
 };
diff --git a/audio/aidl/default/main.cpp b/audio/aidl/default/main.cpp
index 7786cc6..b11af4e 100644
--- a/audio/aidl/default/main.cpp
+++ b/audio/aidl/default/main.cpp
@@ -17,14 +17,14 @@
 #include <cstdlib>
 #include <ctime>
 
-#include "core-impl/Config.h"
-#include "core-impl/Module.h"
-
 #include <android-base/logging.h>
 #include <android/binder_ibinder_platform.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
+#include "core-impl/Config.h"
+#include "core-impl/Module.h"
+
 using aidl::android::hardware::audio::core::Config;
 using aidl::android::hardware::audio::core::Module;
 
@@ -43,14 +43,21 @@
             AServiceManager_addService(config->asBinder().get(), configName.c_str());
     CHECK_EQ(STATUS_OK, status);
 
-    // Make the default module
-    auto moduleDefault = ndk::SharedRefBase::make<Module>();
+    // Make modules
+    auto moduleDefault = ndk::SharedRefBase::make<Module>(Module::Type::DEFAULT);
+    const std::string moduleDefaultName = std::string() + Module::descriptor + "/default";
     AIBinder_setMinSchedulerPolicy(moduleDefault->asBinder().get(), SCHED_NORMAL,
                                    ANDROID_PRIORITY_AUDIO);
-    const std::string moduleDefaultName = std::string() + Module::descriptor + "/default";
     status = AServiceManager_addService(moduleDefault->asBinder().get(), moduleDefaultName.c_str());
     CHECK_EQ(STATUS_OK, status);
 
+    auto moduleRSubmix = ndk::SharedRefBase::make<Module>(Module::Type::R_SUBMIX);
+    const std::string moduleRSubmixName = std::string() + Module::descriptor + "/r_submix";
+    AIBinder_setMinSchedulerPolicy(moduleRSubmix->asBinder().get(), SCHED_NORMAL,
+                                   ANDROID_PRIORITY_AUDIO);
+    status = AServiceManager_addService(moduleRSubmix->asBinder().get(), moduleRSubmixName.c_str());
+    CHECK_EQ(STATUS_OK, status);
+
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
 }
diff --git a/audio/aidl/default/presetReverb/PresetReverbSw.cpp b/audio/aidl/default/presetReverb/PresetReverbSw.cpp
index 069d0ff..1b9d614 100644
--- a/audio/aidl/default/presetReverb/PresetReverbSw.cpp
+++ b/audio/aidl/default/presetReverb/PresetReverbSw.cpp
@@ -25,6 +25,7 @@
 
 #include "PresetReverbSw.h"
 
+using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::kPresetReverbSwImplUUID;
 using aidl::android::hardware::audio::effect::PresetReverbSw;
@@ -47,23 +48,30 @@
     }
 }
 
-extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
-    if (!instanceSp) {
-        return EX_NONE;
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kPresetReverbSwImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
     }
-    State state;
-    ndk::ScopedAStatus status = instanceSp->getState(&state);
-    if (!status.isOk() || State::INIT != state) {
-        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
-                   << " in state: " << toString(state) << ", status: " << status.getDescription();
-        return EX_ILLEGAL_STATE;
-    }
-    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+    *_aidl_return = PresetReverbSw::kDescriptor;
     return EX_NONE;
 }
 
 namespace aidl::android::hardware::audio::effect {
 
+const std::string PresetReverbSw::kEffectName = "PresetReverbSw";
+const PresetReverb::Capability PresetReverbSw::kCapability;
+const Descriptor PresetReverbSw::kDescriptor = {
+        .common = {.id = {.type = kPresetReverbTypeUUID,
+                          .uuid = kPresetReverbSwImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = PresetReverbSw::kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = Capability::make<Capability::presetReverb>(PresetReverbSw::kCapability)};
+
 ndk::ScopedAStatus PresetReverbSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
     *_aidl_return = kDescriptor;
@@ -71,12 +79,10 @@
 }
 
 ndk::ScopedAStatus PresetReverbSw::setParameterSpecific(const Parameter::Specific& specific) {
-    RETURN_IF(Parameter::Specific::reverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+    RETURN_IF(Parameter::Specific::presetReverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
-    std::lock_guard lg(mMutex);
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
-    mSpecificParam = specific.get<Parameter::Specific::reverb>();
+    mSpecificParam = specific.get<Parameter::Specific::presetReverb>();
     LOG(DEBUG) << __func__ << " success with: " << specific.toString();
     return ndk::ScopedAStatus::ok();
 }
@@ -84,17 +90,22 @@
 ndk::ScopedAStatus PresetReverbSw::getParameterSpecific(const Parameter::Id& id,
                                                         Parameter::Specific* specific) {
     auto tag = id.getTag();
-    RETURN_IF(Parameter::Id::reverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
-    specific->set<Parameter::Specific::reverb>(mSpecificParam);
+    RETURN_IF(Parameter::Id::presetReverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    specific->set<Parameter::Specific::presetReverb>(mSpecificParam);
     return ndk::ScopedAStatus::ok();
 }
 
 std::shared_ptr<EffectContext> PresetReverbSw::createContext(const Parameter::Common& common) {
     if (mContext) {
         LOG(DEBUG) << __func__ << " context already exist";
-        return mContext;
+    } else {
+        mContext = std::make_shared<PresetReverbSwContext>(1 /* statusFmqDepth */, common);
     }
-    mContext = std::make_shared<PresetReverbSwContext>(1 /* statusFmqDepth */, common);
+
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> PresetReverbSw::getContext() {
     return mContext;
 }
 
@@ -106,13 +117,13 @@
 }
 
 // Processing method running in EffectWorker thread.
-IEffect::Status PresetReverbSw::effectProcessImpl(float* in, float* out, int process) {
+IEffect::Status PresetReverbSw::effectProcessImpl(float* in, float* out, int samples) {
     // TODO: get data buffer and process.
-    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
-    for (int i = 0; i < process; i++) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    for (int i = 0; i < samples; i++) {
         *out++ = *in++;
     }
-    return {STATUS_OK, process, process};
+    return {STATUS_OK, samples, samples};
 }
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/presetReverb/PresetReverbSw.h b/audio/aidl/default/presetReverb/PresetReverbSw.h
index 75a5a94..43ed36e 100644
--- a/audio/aidl/default/presetReverb/PresetReverbSw.h
+++ b/audio/aidl/default/presetReverb/PresetReverbSw.h
@@ -37,6 +37,9 @@
 
 class PresetReverbSw final : public EffectImpl {
   public:
+    static const std::string kEffectName;
+    static const PresetReverb::Capability kCapability;
+    static const Descriptor kDescriptor;
     PresetReverbSw() { LOG(DEBUG) << __func__; }
     ~PresetReverbSw() {
         cleanUp();
@@ -47,27 +50,17 @@
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
     ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
                                             Parameter::Specific* specific) override;
-    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+
     std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
     RetCode releaseContext() override;
 
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+    std::string getEffectName() override { return kEffectName; }
+
   private:
     std::shared_ptr<PresetReverbSwContext> mContext;
-    /* capabilities */
-    const Reverb::Capability kCapability;
-    /* Effect descriptor */
-    const Descriptor kDescriptor = {
-            .common = {.id = {.type = kPresetReverbTypeUUID,
-                              .uuid = kPresetReverbSwImplUUID,
-                              .proxy = std::nullopt},
-                       .flags = {.type = Flags::Type::INSERT,
-                                 .insert = Flags::Insert::FIRST,
-                                 .volume = Flags::Volume::CTRL},
-                       .name = "PresetReverbSw",
-                       .implementor = "The Android Open Source Project"},
-            .capability = Capability::make<Capability::reverb>(kCapability)};
-
     /* parameters */
-    Reverb mSpecificParam;
+    PresetReverb mSpecificParam;
 };
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/virtualizer/VirtualizerSw.cpp b/audio/aidl/default/virtualizer/VirtualizerSw.cpp
index 9688fc8..faa630e 100644
--- a/audio/aidl/default/virtualizer/VirtualizerSw.cpp
+++ b/audio/aidl/default/virtualizer/VirtualizerSw.cpp
@@ -25,6 +25,7 @@
 
 #include "VirtualizerSw.h"
 
+using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::kVirtualizerSwImplUUID;
 using aidl::android::hardware::audio::effect::State;
@@ -47,23 +48,30 @@
     }
 }
 
-extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
-    if (!instanceSp) {
-        return EX_NONE;
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kVirtualizerSwImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
     }
-    State state;
-    ndk::ScopedAStatus status = instanceSp->getState(&state);
-    if (!status.isOk() || State::INIT != state) {
-        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
-                   << " in state: " << toString(state) << ", status: " << status.getDescription();
-        return EX_ILLEGAL_STATE;
-    }
-    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+    *_aidl_return = VirtualizerSw::kDescriptor;
     return EX_NONE;
 }
 
 namespace aidl::android::hardware::audio::effect {
 
+const std::string VirtualizerSw::kEffectName = "VirtualizerSw";
+const Virtualizer::Capability VirtualizerSw::kCapability;
+const Descriptor VirtualizerSw::kDescriptor = {
+        .common = {.id = {.type = kVirtualizerTypeUUID,
+                          .uuid = kVirtualizerSwImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = VirtualizerSw::kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = Capability::make<Capability::virtualizer>(VirtualizerSw::kCapability)};
+
 ndk::ScopedAStatus VirtualizerSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
     *_aidl_return = kDescriptor;
@@ -73,8 +81,6 @@
 ndk::ScopedAStatus VirtualizerSw::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::virtualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
-    std::lock_guard lg(mMutex);
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     mSpecificParam = specific.get<Parameter::Specific::virtualizer>();
     LOG(DEBUG) << __func__ << " success with: " << specific.toString();
@@ -92,9 +98,14 @@
 std::shared_ptr<EffectContext> VirtualizerSw::createContext(const Parameter::Common& common) {
     if (mContext) {
         LOG(DEBUG) << __func__ << " context already exist";
-        return mContext;
+    } else {
+        mContext = std::make_shared<VirtualizerSwContext>(1 /* statusFmqDepth */, common);
     }
-    mContext = std::make_shared<VirtualizerSwContext>(1 /* statusFmqDepth */, common);
+
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> VirtualizerSw::getContext() {
     return mContext;
 }
 
@@ -106,13 +117,13 @@
 }
 
 // Processing method running in EffectWorker thread.
-IEffect::Status VirtualizerSw::effectProcessImpl(float* in, float* out, int process) {
+IEffect::Status VirtualizerSw::effectProcessImpl(float* in, float* out, int samples) {
     // TODO: get data buffer and process.
-    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
-    for (int i = 0; i < process; i++) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    for (int i = 0; i < samples; i++) {
         *out++ = *in++;
     }
-    return {STATUS_OK, process, process};
+    return {STATUS_OK, samples, samples};
 }
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/virtualizer/VirtualizerSw.h b/audio/aidl/default/virtualizer/VirtualizerSw.h
index e4de8b3..4a05678 100644
--- a/audio/aidl/default/virtualizer/VirtualizerSw.h
+++ b/audio/aidl/default/virtualizer/VirtualizerSw.h
@@ -37,6 +37,9 @@
 
 class VirtualizerSw final : public EffectImpl {
   public:
+    static const std::string kEffectName;
+    static const Virtualizer::Capability kCapability;
+    static const Descriptor kDescriptor;
     VirtualizerSw() { LOG(DEBUG) << __func__; }
     ~VirtualizerSw() {
         cleanUp();
@@ -47,26 +50,16 @@
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
     ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
                                             Parameter::Specific* specific) override;
-    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+
     std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
     RetCode releaseContext() override;
 
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+    std::string getEffectName() override { return kEffectName; }
+
   private:
     std::shared_ptr<VirtualizerSwContext> mContext;
-    /* capabilities */
-    const Virtualizer::Capability kCapability;
-    /* Effect descriptor */
-    const Descriptor kDescriptor = {
-            .common = {.id = {.type = kVirtualizerTypeUUID,
-                              .uuid = kVirtualizerSwImplUUID,
-                              .proxy = std::nullopt},
-                       .flags = {.type = Flags::Type::INSERT,
-                                 .insert = Flags::Insert::FIRST,
-                                 .volume = Flags::Volume::CTRL},
-                       .name = "VirtualizerSw",
-                       .implementor = "The Android Open Source Project"},
-            .capability = Capability::make<Capability::virtualizer>(kCapability)};
-
     /* parameters */
     Virtualizer mSpecificParam;
 };
diff --git a/audio/aidl/default/visualizer/VisualizerSw.cpp b/audio/aidl/default/visualizer/VisualizerSw.cpp
index 24a7bef..b898c00 100644
--- a/audio/aidl/default/visualizer/VisualizerSw.cpp
+++ b/audio/aidl/default/visualizer/VisualizerSw.cpp
@@ -25,6 +25,7 @@
 
 #include "VisualizerSw.h"
 
+using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::kVisualizerSwImplUUID;
 using aidl::android::hardware::audio::effect::State;
@@ -47,23 +48,30 @@
     }
 }
 
-extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
-    if (!instanceSp) {
-        return EX_NONE;
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kVisualizerSwImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
     }
-    State state;
-    ndk::ScopedAStatus status = instanceSp->getState(&state);
-    if (!status.isOk() || State::INIT != state) {
-        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
-                   << " in state: " << toString(state) << ", status: " << status.getDescription();
-        return EX_ILLEGAL_STATE;
-    }
-    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+    *_aidl_return = VisualizerSw::kDescriptor;
     return EX_NONE;
 }
 
 namespace aidl::android::hardware::audio::effect {
 
+const std::string VisualizerSw::kEffectName = "VisualizerSw";
+const Visualizer::Capability VisualizerSw::kCapability;
+const Descriptor VisualizerSw::kDescriptor = {
+        .common = {.id = {.type = kVisualizerTypeUUID,
+                          .uuid = kVisualizerSwImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = VisualizerSw::kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = Capability::make<Capability::visualizer>(VisualizerSw::kCapability)};
+
 ndk::ScopedAStatus VisualizerSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
     *_aidl_return = kDescriptor;
@@ -73,8 +81,6 @@
 ndk::ScopedAStatus VisualizerSw::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
-    std::lock_guard lg(mMutex);
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     mSpecificParam = specific.get<Parameter::Specific::visualizer>();
     LOG(DEBUG) << __func__ << " success with: " << specific.toString();
@@ -92,9 +98,14 @@
 std::shared_ptr<EffectContext> VisualizerSw::createContext(const Parameter::Common& common) {
     if (mContext) {
         LOG(DEBUG) << __func__ << " context already exist";
-        return mContext;
+    } else {
+        mContext = std::make_shared<VisualizerSwContext>(1 /* statusFmqDepth */, common);
     }
-    mContext = std::make_shared<VisualizerSwContext>(1 /* statusFmqDepth */, common);
+
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> VisualizerSw::getContext() {
     return mContext;
 }
 
@@ -106,13 +117,13 @@
 }
 
 // Processing method running in EffectWorker thread.
-IEffect::Status VisualizerSw::effectProcessImpl(float* in, float* out, int process) {
+IEffect::Status VisualizerSw::effectProcessImpl(float* in, float* out, int samples) {
     // TODO: get data buffer and process.
-    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
-    for (int i = 0; i < process; i++) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    for (int i = 0; i < samples; i++) {
         *out++ = *in++;
     }
-    return {STATUS_OK, process, process};
+    return {STATUS_OK, samples, samples};
 }
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/visualizer/VisualizerSw.h b/audio/aidl/default/visualizer/VisualizerSw.h
index bccd6e9..24b92dd 100644
--- a/audio/aidl/default/visualizer/VisualizerSw.h
+++ b/audio/aidl/default/visualizer/VisualizerSw.h
@@ -37,6 +37,9 @@
 
 class VisualizerSw final : public EffectImpl {
   public:
+    static const std::string kEffectName;
+    static const Visualizer::Capability kCapability;
+    static const Descriptor kDescriptor;
     VisualizerSw() { LOG(DEBUG) << __func__; }
     ~VisualizerSw() {
         cleanUp();
@@ -47,26 +50,16 @@
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
     ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
                                             Parameter::Specific* specific) override;
-    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+
     std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
     RetCode releaseContext() override;
 
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+    std::string getEffectName() override { return kEffectName; }
+
   private:
     std::shared_ptr<VisualizerSwContext> mContext;
-    /* capabilities */
-    const Visualizer::Capability kCapability;
-    /* Effect descriptor */
-    const Descriptor kDescriptor = {
-            .common = {.id = {.type = kVisualizerTypeUUID,
-                              .uuid = kVisualizerSwImplUUID,
-                              .proxy = std::nullopt},
-                       .flags = {.type = Flags::Type::INSERT,
-                                 .insert = Flags::Insert::FIRST,
-                                 .volume = Flags::Volume::CTRL},
-                       .name = "VisualizerSw",
-                       .implementor = "The Android Open Source Project"},
-            .capability = Capability::make<Capability::visualizer>(kCapability)};
-
     /* parameters */
     Visualizer mSpecificParam;
 };
diff --git a/audio/aidl/default/volume/VolumeSw.cpp b/audio/aidl/default/volume/VolumeSw.cpp
index b8af921..6fce16e 100644
--- a/audio/aidl/default/volume/VolumeSw.cpp
+++ b/audio/aidl/default/volume/VolumeSw.cpp
@@ -25,6 +25,7 @@
 
 #include "VolumeSw.h"
 
+using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::hardware::audio::effect::kVolumeSwImplUUID;
 using aidl::android::hardware::audio::effect::State;
@@ -47,23 +48,30 @@
     }
 }
 
-extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
-    if (!instanceSp) {
-        return EX_NONE;
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != kVolumeSwImplUUID) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
     }
-    State state;
-    ndk::ScopedAStatus status = instanceSp->getState(&state);
-    if (!status.isOk() || State::INIT != state) {
-        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
-                   << " in state: " << toString(state) << ", status: " << status.getDescription();
-        return EX_ILLEGAL_STATE;
-    }
-    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+    *_aidl_return = VolumeSw::kDescriptor;
     return EX_NONE;
 }
 
 namespace aidl::android::hardware::audio::effect {
 
+const std::string VolumeSw::kEffectName = "VolumeSw";
+const Volume::Capability VolumeSw::kCapability;
+const Descriptor VolumeSw::kDescriptor = {
+        .common = {.id = {.type = kVolumeTypeUUID,
+                          .uuid = kVolumeSwImplUUID,
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = VolumeSw::kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = Capability::make<Capability::volume>(VolumeSw::kCapability)};
+
 ndk::ScopedAStatus VolumeSw::getDescriptor(Descriptor* _aidl_return) {
     LOG(DEBUG) << __func__ << kDescriptor.toString();
     *_aidl_return = kDescriptor;
@@ -73,8 +81,6 @@
 ndk::ScopedAStatus VolumeSw::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::volume != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
-    std::lock_guard lg(mMutex);
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
 
     mSpecificParam = specific.get<Parameter::Specific::volume>();
     LOG(DEBUG) << __func__ << " success with: " << specific.toString();
@@ -92,9 +98,14 @@
 std::shared_ptr<EffectContext> VolumeSw::createContext(const Parameter::Common& common) {
     if (mContext) {
         LOG(DEBUG) << __func__ << " context already exist";
-        return mContext;
+    } else {
+        mContext = std::make_shared<VolumeSwContext>(1 /* statusFmqDepth */, common);
     }
-    mContext = std::make_shared<VolumeSwContext>(1 /* statusFmqDepth */, common);
+
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> VolumeSw::getContext() {
     return mContext;
 }
 
@@ -106,13 +117,13 @@
 }
 
 // Processing method running in EffectWorker thread.
-IEffect::Status VolumeSw::effectProcessImpl(float* in, float* out, int process) {
+IEffect::Status VolumeSw::effectProcessImpl(float* in, float* out, int samples) {
     // TODO: get data buffer and process.
-    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
-    for (int i = 0; i < process; i++) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    for (int i = 0; i < samples; i++) {
         *out++ = *in++;
     }
-    return {STATUS_OK, process, process};
+    return {STATUS_OK, samples, samples};
 }
 
 }  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/volume/VolumeSw.h b/audio/aidl/default/volume/VolumeSw.h
index 86e01c1..3bd29b9 100644
--- a/audio/aidl/default/volume/VolumeSw.h
+++ b/audio/aidl/default/volume/VolumeSw.h
@@ -37,6 +37,9 @@
 
 class VolumeSw final : public EffectImpl {
   public:
+    static const std::string kEffectName;
+    static const Volume::Capability kCapability;
+    static const Descriptor kDescriptor;
     VolumeSw() { LOG(DEBUG) << __func__; }
     ~VolumeSw() {
         cleanUp();
@@ -47,26 +50,16 @@
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
     ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
                                             Parameter::Specific* specific) override;
-    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+
     std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
     RetCode releaseContext() override;
 
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+    std::string getEffectName() override { return kEffectName; }
+
   private:
     std::shared_ptr<VolumeSwContext> mContext;
-    /* capabilities */
-    const Volume::Capability kCapability;
-    /* Effect descriptor */
-    const Descriptor kDescriptor = {
-            .common = {.id = {.type = kVolumeTypeUUID,
-                              .uuid = kVolumeSwImplUUID,
-                              .proxy = std::nullopt},
-                       .flags = {.type = Flags::Type::INSERT,
-                                 .insert = Flags::Insert::FIRST,
-                                 .volume = Flags::Volume::CTRL},
-                       .name = "VolumeSw",
-                       .implementor = "The Android Open Source Project"},
-            .capability = Capability::make<Capability::volume>(kCapability)};
-
     /* parameters */
     Volume mSpecificParam;
 };
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 03e9fca..068742d 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -49,7 +49,8 @@
     ],
     srcs: [
         "ModuleConfig.cpp",
-        "VtsHalAudioCoreTargetTest.cpp",
+        "VtsHalAudioCoreConfigTargetTest.cpp",
+        "VtsHalAudioCoreModuleTargetTest.cpp",
     ],
 }
 
@@ -66,6 +67,12 @@
 }
 
 cc_test {
+    name: "VtsHalBassBoostTargetTest",
+    defaults: ["VtsHalAudioTargetTestDefaults"],
+    srcs: ["VtsHalBassBoostTargetTest.cpp"],
+}
+
+cc_test {
     name: "VtsHalEqualizerTargetTest",
     defaults: ["VtsHalAudioTargetTestDefaults"],
     srcs: ["VtsHalEqualizerTargetTest.cpp"],
diff --git a/audio/aidl/vts/EffectFactoryHelper.h b/audio/aidl/vts/EffectFactoryHelper.h
index dc766dd..b649d9e 100644
--- a/audio/aidl/vts/EffectFactoryHelper.h
+++ b/audio/aidl/vts/EffectFactoryHelper.h
@@ -58,9 +58,11 @@
         for (const auto& name : names) {
             auto factory = IFactory::fromBinder(util.connectToService(name));
             if (factory) {
-                if (std::vector<Descriptor::Identity> ids;
-                    factory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids).isOk()) {
-                    for (const auto& id : ids) {
+                if (std::vector<Descriptor> descs;
+                    factory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs)
+                            .isOk()) {
+                    for (const auto& desc : descs) {
+                        const auto& id = desc.common.id;
                         if (type.has_value() && id.type != type.value()) {
                             continue;
                         }
diff --git a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
new file mode 100644
index 0000000..bf73648
--- /dev/null
+++ b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
@@ -0,0 +1,333 @@
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#define LOG_TAG "VtsHalAudioCore.Config"
+
+#include <Utils.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/audio/core/IConfig.h>
+
+#include "AudioHalBinderServiceUtil.h"
+#include "TestUtils.h"
+
+using namespace android;
+using aidl::android::hardware::audio::core::IConfig;
+using aidl::android::media::audio::common::AudioAttributes;
+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::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::AudioProductStrategyType;
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::AudioStreamType;
+using aidl::android::media::audio::common::AudioUsage;
+
+class AudioCoreConfig : public testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(ConnectToService()); }
+    void ConnectToService() {
+        mConfig = IConfig::fromBinder(mBinderUtil.connectToService(GetParam()));
+        ASSERT_NE(mConfig, nullptr);
+    }
+
+    void RestartService() {
+        ASSERT_NE(mConfig, nullptr);
+        mEngineConfig.reset();
+        mConfig = IConfig::fromBinder(mBinderUtil.restartService());
+        ASSERT_NE(mConfig, nullptr);
+    }
+
+    void SetUpEngineConfig() {
+        if (mEngineConfig == nullptr) {
+            auto tempConfig = std::make_unique<AudioHalEngineConfig>();
+            ASSERT_IS_OK(mConfig->getEngineConfig(tempConfig.get()));
+            mEngineConfig = std::move(tempConfig);
+        }
+    }
+
+    static bool IsProductStrategyTypeReservedForSystemUse(const AudioProductStrategyType& pst) {
+        switch (pst) {
+            case AudioProductStrategyType::SYS_RESERVED_NONE:
+            case AudioProductStrategyType::SYS_RESERVED_REROUTING:
+            case AudioProductStrategyType::SYS_RESERVED_CALL_ASSISTANT:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    static bool IsStreamTypeReservedForSystemUse(const AudioStreamType& streamType) {
+        switch (streamType) {
+            case AudioStreamType::SYS_RESERVED_DEFAULT:
+            case AudioStreamType::SYS_RESERVED_REROUTING:
+            case AudioStreamType::SYS_RESERVED_PATCH:
+            case AudioStreamType::CALL_ASSISTANT:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    static bool IsAudioUsageValid(const AudioUsage& usage) {
+        switch (usage) {
+            case AudioUsage::INVALID:
+            case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST:
+            case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT:
+            case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED:
+                return false;
+            default:
+                return true;
+        }
+    }
+
+    static bool IsAudioSourceValid(const AudioSource& source) {
+        return (source != AudioSource::SYS_RESERVED_INVALID);
+    }
+
+    static const std::unordered_set<int>& GetSupportedAudioProductStrategyTypes() {
+        static const std::unordered_set<int> supportedAudioProductStrategyTypes = []() {
+            std::unordered_set<int> supportedStrategyTypes;
+            for (const auto& audioProductStrategyType :
+                 ndk::enum_range<AudioProductStrategyType>()) {
+                if (!IsProductStrategyTypeReservedForSystemUse(audioProductStrategyType)) {
+                    supportedStrategyTypes.insert(static_cast<int>(audioProductStrategyType));
+                }
+            }
+            return supportedStrategyTypes;
+        }();
+        return supportedAudioProductStrategyTypes;
+    }
+
+    static int GetSupportedAudioFlagsMask() {
+        static const int supportedAudioFlagsMask = []() {
+            int mask = 0;
+            for (const auto& audioFlag : ndk::enum_range<AudioFlag>()) {
+                mask |= static_cast<int>(audioFlag);
+            }
+            return mask;
+        }();
+        return supportedAudioFlagsMask;
+    }
+
+    /**
+     * Verify streamType is not INVALID if using default engine.
+     * Verify that streamType is a valid AudioStreamType if the associated
+     * volumeGroup minIndex/maxIndex is INDEX_DEFERRED_TO_AUDIO_SERVICE.
+     */
+    void ValidateAudioStreamType(const AudioStreamType& streamType,
+                                 const AudioHalVolumeGroup& associatedVolumeGroup) {
+        EXPECT_FALSE(IsStreamTypeReservedForSystemUse(streamType));
+        if (!mEngineConfig->capSpecificConfig ||
+            associatedVolumeGroup.minIndex ==
+                    AudioHalVolumeGroup::INDEX_DEFERRED_TO_AUDIO_SERVICE) {
+            EXPECT_NE(streamType, AudioStreamType::INVALID);
+        }
+    }
+
+    /**
+     * Verify contained enum types are valid.
+     */
+    void ValidateAudioAttributes(const AudioAttributes& attributes) {
+        // No need to check contentType; there are no INVALID or SYS_RESERVED values
+        EXPECT_TRUE(IsAudioUsageValid(attributes.usage));
+        EXPECT_TRUE(IsAudioSourceValid(attributes.source));
+        EXPECT_EQ(attributes.flags & ~GetSupportedAudioFlagsMask(), 0);
+    }
+
+    /**
+     * Verify volumeGroupName corresponds to an AudioHalVolumeGroup.
+     * Validate contained types.
+     */
+    void ValidateAudioHalAttributesGroup(
+            const AudioHalAttributesGroup& attributesGroup,
+            std::unordered_map<std::string, const AudioHalVolumeGroup&>& volumeGroupMap,
+            std::unordered_set<std::string>& volumeGroupsUsedInStrategies) {
+        bool isVolumeGroupNameValid = volumeGroupMap.count(attributesGroup.volumeGroupName);
+        EXPECT_TRUE(isVolumeGroupNameValid);
+        EXPECT_NO_FATAL_FAILURE(ValidateAudioStreamType(
+                attributesGroup.streamType, volumeGroupMap.at(attributesGroup.volumeGroupName)));
+        if (isVolumeGroupNameValid) {
+            volumeGroupsUsedInStrategies.insert(attributesGroup.volumeGroupName);
+        }
+        for (const AudioAttributes& attr : attributesGroup.attributes) {
+            EXPECT_NO_FATAL_FAILURE(ValidateAudioAttributes(attr));
+        }
+    }
+
+    /**
+     * Default engine: verify productStrategy.id is valid AudioProductStrategyType.
+     * CAP engine: verify productStrategy.id is either valid AudioProductStrategyType
+     * or is >= VENDOR_STRATEGY_ID_START.
+     * Validate contained types.
+     */
+    void ValidateAudioHalProductStrategy(
+            const AudioHalProductStrategy& strategy,
+            std::unordered_map<std::string, const AudioHalVolumeGroup&>& volumeGroupMap,
+            std::unordered_set<std::string>& volumeGroupsUsedInStrategies) {
+        if (!mEngineConfig->capSpecificConfig ||
+            (strategy.id < AudioHalProductStrategy::VENDOR_STRATEGY_ID_START)) {
+            EXPECT_NE(GetSupportedAudioProductStrategyTypes().find(strategy.id),
+                      GetSupportedAudioProductStrategyTypes().end());
+        }
+        for (const AudioHalAttributesGroup& attributesGroup : strategy.attributesGroups) {
+            EXPECT_NO_FATAL_FAILURE(ValidateAudioHalAttributesGroup(attributesGroup, volumeGroupMap,
+                                                                    volumeGroupsUsedInStrategies));
+        }
+    }
+
+    /**
+     * Verify curve point index is in [CurvePoint::MIN_INDEX, CurvePoint::MAX_INDEX].
+     */
+    void ValidateAudioHalVolumeCurve(const AudioHalVolumeCurve& volumeCurve) {
+        for (const AudioHalVolumeCurve::CurvePoint& curvePoint : volumeCurve.curvePoints) {
+            EXPECT_TRUE(curvePoint.index >= AudioHalVolumeCurve::CurvePoint::MIN_INDEX);
+            EXPECT_TRUE(curvePoint.index <= AudioHalVolumeCurve::CurvePoint::MAX_INDEX);
+        }
+    }
+
+    /**
+     * Verify minIndex, maxIndex are non-negative.
+     * Verify minIndex <= maxIndex.
+     * Verify no two volume curves use the same device category.
+     * Validate contained types.
+     */
+    void ValidateAudioHalVolumeGroup(const AudioHalVolumeGroup& volumeGroup) {
+        /**
+         * Legacy volume curves in audio_policy_configuration.xsd don't use
+         * minIndex or maxIndex. Use of audio_policy_configuration.xml still
+         * allows, and in some cases, relies on, AudioService to provide the min
+         * and max indices for a volumeGroup. From the VTS perspective, there is
+         * no way to differentiate between use of audio_policy_configuration.xml
+         * or audio_policy_engine_configuration.xml, as either one can be used
+         * for the default audio policy engine.
+         */
+        if (volumeGroup.minIndex != AudioHalVolumeGroup::INDEX_DEFERRED_TO_AUDIO_SERVICE ||
+            volumeGroup.maxIndex != AudioHalVolumeGroup::INDEX_DEFERRED_TO_AUDIO_SERVICE) {
+            EXPECT_TRUE(volumeGroup.minIndex >= 0);
+            EXPECT_TRUE(volumeGroup.maxIndex >= 0);
+        }
+        EXPECT_TRUE(volumeGroup.minIndex <= volumeGroup.maxIndex);
+        std::unordered_set<AudioHalVolumeCurve::DeviceCategory> deviceCategorySet;
+        for (const AudioHalVolumeCurve& volumeCurve : volumeGroup.volumeCurves) {
+            EXPECT_TRUE(deviceCategorySet.insert(volumeCurve.deviceCategory).second);
+            EXPECT_NO_FATAL_FAILURE(ValidateAudioHalVolumeCurve(volumeCurve));
+        }
+    }
+
+    /**
+     * Verify defaultLiteralValue is empty for inclusive criterion.
+     */
+    void ValidateAudioHalCapCriterion(const AudioHalCapCriterion& criterion,
+                                      const AudioHalCapCriterionType& criterionType) {
+        if (criterionType.isInclusive) {
+            EXPECT_TRUE(criterion.defaultLiteralValue.empty());
+        }
+    }
+
+    /**
+     * Verify values only contain alphanumeric characters.
+     */
+    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());
+        }
+    }
+
+    /**
+     * 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.
+     */
+    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);
+        }
+        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());
+    }
+
+    /**
+     * Verify VolumeGroups are non-empty.
+     * Verify defaultProductStrategyId matches one of the provided productStrategies.
+     * Otherwise, must be left uninitialized.
+     * Verify each volumeGroup has a unique name.
+     * Verify each productStrategy has a unique id.
+     * Verify each volumeGroup is used in a product strategy.
+     * CAP engine: verify productStrategies are non-empty.
+     * Validate contained types.
+     */
+    void ValidateAudioHalEngineConfig() {
+        EXPECT_NE(mEngineConfig->volumeGroups.size(), 0UL);
+        std::unordered_map<std::string, const AudioHalVolumeGroup&> volumeGroupMap;
+        for (const AudioHalVolumeGroup& volumeGroup : mEngineConfig->volumeGroups) {
+            EXPECT_TRUE(volumeGroupMap.insert({volumeGroup.name, volumeGroup}).second);
+            EXPECT_NO_FATAL_FAILURE(ValidateAudioHalVolumeGroup(volumeGroup));
+        }
+        if (!mEngineConfig->productStrategies.empty()) {
+            std::unordered_set<int> productStrategyIdSet;
+            std::unordered_set<std::string> volumeGroupsUsedInStrategies;
+            for (const AudioHalProductStrategy& strategy : mEngineConfig->productStrategies) {
+                EXPECT_TRUE(productStrategyIdSet.insert(strategy.id).second);
+                EXPECT_NO_FATAL_FAILURE(ValidateAudioHalProductStrategy(
+                        strategy, volumeGroupMap, volumeGroupsUsedInStrategies));
+            }
+            EXPECT_TRUE(productStrategyIdSet.count(mEngineConfig->defaultProductStrategyId))
+                    << "defaultProductStrategyId doesn't match any of the provided "
+                       "productStrategies";
+            EXPECT_EQ(volumeGroupMap.size(), volumeGroupsUsedInStrategies.size());
+        } else {
+            EXPECT_EQ(mEngineConfig->defaultProductStrategyId,
+                      static_cast<int>(AudioProductStrategyType::SYS_RESERVED_NONE))
+                    << "defaultProductStrategyId defined, but no productStrategies were provided";
+        }
+        if (mEngineConfig->capSpecificConfig) {
+            EXPECT_NO_FATAL_FAILURE(
+                    ValidateCapSpecificConfig(mEngineConfig->capSpecificConfig.value()));
+            EXPECT_FALSE(mEngineConfig->productStrategies.empty());
+        }
+    }
+
+  private:
+    std::shared_ptr<IConfig> mConfig;
+    std::unique_ptr<AudioHalEngineConfig> mEngineConfig;
+    AudioHalBinderServiceUtil mBinderUtil;
+};
+
+TEST_P(AudioCoreConfig, Published) {
+    // SetUp must complete with no failures.
+}
+
+TEST_P(AudioCoreConfig, CanBeRestarted) {
+    ASSERT_NO_FATAL_FAILURE(RestartService());
+}
+
+TEST_P(AudioCoreConfig, GetEngineConfigIsValid) {
+    ASSERT_NO_FATAL_FAILURE(SetUpEngineConfig());
+    EXPECT_NO_FATAL_FAILURE(ValidateAudioHalEngineConfig());
+}
+
+INSTANTIATE_TEST_SUITE_P(AudioCoreConfigTest, AudioCoreConfig,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IConfig::descriptor)),
+                         android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreConfig);
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
similarity index 98%
rename from audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
rename to audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index c0c04f4..99771e6 100644
--- a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -27,7 +27,7 @@
 #include <variant>
 #include <vector>
 
-#define LOG_TAG "VtsHalAudioCore"
+#define LOG_TAG "VtsHalAudioCore.Module"
 #include <android-base/logging.h>
 
 #include <StreamWorker.h>
@@ -79,6 +79,7 @@
 using aidl::android::media::audio::common::AudioUsage;
 using aidl::android::media::audio::common::Void;
 using android::hardware::audio::common::isBitPositionFlagSet;
+using android::hardware::audio::common::isTelephonyDeviceType;
 using android::hardware::audio::common::StreamLogic;
 using android::hardware::audio::common::StreamWorker;
 using ndk::enum_range;
@@ -490,16 +491,16 @@
   private:
     StreamDescriptor::State getState() const { return mSteps[mCurrentStep].second; }
     bool isBurstBifurcation() {
-        return getTrigger() == TransitionTrigger{kBurstCommand}&& getState() ==
-               StreamDescriptor::State::TRANSFERRING;
+        return getTrigger() == TransitionTrigger{kBurstCommand} &&
+               getState() == StreamDescriptor::State::TRANSFERRING;
     }
     bool isPauseBifurcation() {
-        return getTrigger() == TransitionTrigger{kPauseCommand}&& getState() ==
-               StreamDescriptor::State::TRANSFER_PAUSED;
+        return getTrigger() == TransitionTrigger{kPauseCommand} &&
+               getState() == StreamDescriptor::State::TRANSFER_PAUSED;
     }
     bool isStartBifurcation() {
-        return getTrigger() == TransitionTrigger{kStartCommand}&& getState() ==
-               StreamDescriptor::State::TRANSFERRING;
+        return getTrigger() == TransitionTrigger{kStartCommand} &&
+               getState() == StreamDescriptor::State::TRANSFERRING;
     }
     const std::vector<StateTransition> mSteps;
     size_t mCurrentStep = 0;
@@ -1902,9 +1903,13 @@
 using AudioStreamIn = AudioStream<IStreamIn>;
 using AudioStreamOut = AudioStream<IStreamOut>;
 
-#define TEST_IN_AND_OUT_STREAM(method_name)                                        \
-    TEST_P(AudioStreamIn, method_name) { ASSERT_NO_FATAL_FAILURE(method_name()); } \
-    TEST_P(AudioStreamOut, method_name) { ASSERT_NO_FATAL_FAILURE(method_name()); }
+#define TEST_IN_AND_OUT_STREAM(method_name)     \
+    TEST_P(AudioStreamIn, method_name) {        \
+        ASSERT_NO_FATAL_FAILURE(method_name()); \
+    }                                           \
+    TEST_P(AudioStreamOut, method_name) {       \
+        ASSERT_NO_FATAL_FAILURE(method_name()); \
+    }
 
 TEST_IN_AND_OUT_STREAM(CloseTwice);
 TEST_IN_AND_OUT_STREAM(OpenAllConfigs);
@@ -2216,9 +2221,9 @@
         }
     }
 
-    bool ValidateObservablePosition(const AudioPortConfig& /*portConfig*/) {
-        // May return false based on the portConfig, e.g. for telephony ports.
-        return true;
+    bool ValidateObservablePosition(const AudioPortConfig& devicePortConfig) {
+        return !isTelephonyDeviceType(
+                devicePortConfig.ext.get<AudioPortExt::Tag::device>().device.type.type);
     }
 
     // Set up a patch first, then open a stream.
@@ -2243,7 +2248,7 @@
         worker.join();
         EXPECT_FALSE(worker.hasError()) << worker.getError();
         EXPECT_EQ("", driver.getUnexpectedStateTransition());
-        if (ValidateObservablePosition(portConfig)) {
+        if (ValidateObservablePosition(devicePortConfig)) {
             EXPECT_TRUE(driver.hasObservablePositionIncrease());
             EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
         }
@@ -2271,7 +2276,7 @@
         worker.join();
         EXPECT_FALSE(worker.hasError()) << worker.getError();
         EXPECT_EQ("", driver.getUnexpectedStateTransition());
-        if (ValidateObservablePosition(portConfig)) {
+        if (ValidateObservablePosition(devicePortConfig)) {
             EXPECT_TRUE(driver.hasObservablePositionIncrease());
             EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
         }
@@ -2280,9 +2285,13 @@
 using AudioStreamIoIn = AudioStreamIo<IStreamIn>;
 using AudioStreamIoOut = AudioStreamIo<IStreamOut>;
 
-#define TEST_IN_AND_OUT_STREAM_IO(method_name)                                       \
-    TEST_P(AudioStreamIoIn, method_name) { ASSERT_NO_FATAL_FAILURE(method_name()); } \
-    TEST_P(AudioStreamIoOut, method_name) { ASSERT_NO_FATAL_FAILURE(method_name()); }
+#define TEST_IN_AND_OUT_STREAM_IO(method_name)  \
+    TEST_P(AudioStreamIoIn, method_name) {      \
+        ASSERT_NO_FATAL_FAILURE(method_name()); \
+    }                                           \
+    TEST_P(AudioStreamIoOut, method_name) {     \
+        ASSERT_NO_FATAL_FAILURE(method_name()); \
+    }
 
 TEST_IN_AND_OUT_STREAM_IO(Run);
 
@@ -2435,9 +2444,13 @@
 
 // Not all tests require both directions, so parametrization would require
 // more abstractions.
-#define TEST_PATCH_BOTH_DIRECTIONS(method_name)                                                  \
-    TEST_P(AudioModulePatch, method_name##Input) { ASSERT_NO_FATAL_FAILURE(method_name(true)); } \
-    TEST_P(AudioModulePatch, method_name##Output) { ASSERT_NO_FATAL_FAILURE(method_name(false)); }
+#define TEST_PATCH_BOTH_DIRECTIONS(method_name)      \
+    TEST_P(AudioModulePatch, method_name##Input) {   \
+        ASSERT_NO_FATAL_FAILURE(method_name(true));  \
+    }                                                \
+    TEST_P(AudioModulePatch, method_name##Output) {  \
+        ASSERT_NO_FATAL_FAILURE(method_name(false)); \
+    }
 
 TEST_PATCH_BOTH_DIRECTIONS(ResetPortConfigUsedByPatch);
 TEST_PATCH_BOTH_DIRECTIONS(SetInvalidPatch);
diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
index 8ae963e..21f5eb5 100644
--- a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -65,8 +65,10 @@
     std::unique_ptr<EffectFactoryHelper> mFactoryHelper;
     std::shared_ptr<IFactory> mEffectFactory;
     std::vector<std::shared_ptr<IEffect>> mEffects;
-    const Descriptor::Identity kNullDesc = {.uuid = kEffectNullUuid};
-    const Descriptor::Identity kZeroDesc = {.uuid = kEffectZeroUuid};
+    const Descriptor::Identity kNullId = {.uuid = kEffectNullUuid};
+    const Descriptor::Identity kZeroId = {.uuid = kEffectZeroUuid};
+    const Descriptor kNullDesc = {.common.id = kNullId};
+    const Descriptor kZeroDesc = {.common.id = kZeroId};
 
     template <typename Functor>
     void ForEachId(const std::vector<Descriptor::Identity> ids, Functor functor) {
@@ -82,15 +84,15 @@
         }
     }
 
-    std::vector<std::shared_ptr<IEffect>> createWithIds(
-            const std::vector<Descriptor::Identity> ids,
-            const binder_status_t expectStatus = EX_NONE) {
+    std::vector<std::shared_ptr<IEffect>> createWithDescs(
+            const std::vector<Descriptor> descs, const binder_status_t expectStatus = EX_NONE) {
         std::vector<std::shared_ptr<IEffect>> effects;
-        for (const auto& id : ids) {
+        for (const auto& desc : descs) {
+            const auto& uuid = desc.common.id.uuid;
             std::shared_ptr<IEffect> effect;
-            EXPECT_STATUS(expectStatus, mEffectFactory->createEffect(id.uuid, &effect));
+            EXPECT_STATUS(expectStatus, mEffectFactory->createEffect(uuid, &effect));
             if (expectStatus == EX_NONE) {
-                EXPECT_NE(effect, nullptr) << " null effect with uuid: " << id.uuid.toString();
+                EXPECT_NE(effect, nullptr) << " null effect with uuid: " << uuid.toString();
                 effects.push_back(std::move(effect));
             }
         }
@@ -102,9 +104,9 @@
             EXPECT_STATUS(expectStatus, mEffectFactory->destroyEffect(effect));
         }
     }
-    void creatAndDestroyIds(const std::vector<Descriptor::Identity> ids) {
-        for (const auto& id : ids) {
-            auto effects = createWithIds({id});
+    void creatAndDestroyDescs(const std::vector<Descriptor> descs) {
+        for (const auto& desc : descs) {
+            auto effects = createWithDescs({desc});
             ASSERT_NO_FATAL_FAILURE(destroyEffects(effects));
         }
     }
@@ -128,7 +130,7 @@
  * https://developer.android.com/reference/android/media/audiofx/AudioEffect
  */
 TEST_P(EffectFactoryTest, ExpectAllAospEffectTypes) {
-    std::vector<Descriptor::Identity> ids;
+    std::vector<Descriptor> descs;
     std::set<AudioUuid> typeUuidSet(
             {aidl::android::hardware::audio::effect::kBassBoostTypeUUID,
              aidl::android::hardware::audio::effect::kEqualizerTypeUUID,
@@ -138,10 +140,10 @@
              aidl::android::hardware::audio::effect::kHapticGeneratorTypeUUID,
              aidl::android::hardware::audio::effect::kVirtualizerTypeUUID});
 
-    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
-    EXPECT_TRUE(ids.size() >= typeUuidSet.size());
-    for (const auto& id : ids) {
-        typeUuidSet.erase(id.type);
+    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
+    EXPECT_TRUE(descs.size() >= typeUuidSet.size());
+    for (const auto& desc : descs) {
+        typeUuidSet.erase(desc.common.id.type);
     }
     std::string msg = " missing type UUID:\n";
     for (const auto& uuid : typeUuidSet) {
@@ -152,46 +154,46 @@
 }
 
 TEST_P(EffectFactoryTest, QueryNullTypeUuid) {
-    std::vector<Descriptor::Identity> ids;
-    EXPECT_IS_OK(mEffectFactory->queryEffects(kEffectNullUuid, std::nullopt, std::nullopt, &ids));
-    EXPECT_EQ(ids.size(), 0UL);
+    std::vector<Descriptor> descs;
+    EXPECT_IS_OK(mEffectFactory->queryEffects(kEffectNullUuid, std::nullopt, std::nullopt, &descs));
+    EXPECT_EQ(descs.size(), 0UL);
 }
 
 TEST_P(EffectFactoryTest, QueriedNullImplUuid) {
-    std::vector<Descriptor::Identity> ids;
-    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, kEffectNullUuid, std::nullopt, &ids));
-    EXPECT_EQ(ids.size(), 0UL);
+    std::vector<Descriptor> descs;
+    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, kEffectNullUuid, std::nullopt, &descs));
+    EXPECT_EQ(descs.size(), 0UL);
 }
 
 TEST_P(EffectFactoryTest, QueriedNullProxyUuid) {
-    std::vector<Descriptor::Identity> ids;
-    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, kEffectNullUuid, &ids));
-    EXPECT_EQ(ids.size(), 0UL);
+    std::vector<Descriptor> descs;
+    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, kEffectNullUuid, &descs));
+    EXPECT_EQ(descs.size(), 0UL);
 }
 
 // create all effects, and then destroy them all together
 TEST_P(EffectFactoryTest, CreateAndDestroyEffects) {
-    std::vector<Descriptor::Identity> ids;
-    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
-    EXPECT_NE(ids.size(), 0UL);
+    std::vector<Descriptor> descs;
+    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
+    EXPECT_NE(descs.size(), 0UL);
 
     std::vector<std::shared_ptr<IEffect>> effects;
-    effects = createWithIds(ids);
-    EXPECT_EQ(ids.size(), effects.size());
+    effects = createWithDescs(descs);
+    EXPECT_EQ(descs.size(), effects.size());
     destroyEffects(effects);
 }
 
 TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
-    std::vector<Descriptor::Identity> ids;
-    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
-    EXPECT_NE(ids.size(), 0UL);
+    std::vector<Descriptor> descs;
+    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
+    EXPECT_NE(descs.size(), 0UL);
 
-    std::vector<std::shared_ptr<IEffect>> effects = createWithIds(ids);
-    EXPECT_EQ(ids.size(), effects.size());
-    std::vector<std::shared_ptr<IEffect>> effects2 = createWithIds(ids);
-    EXPECT_EQ(ids.size(), effects2.size());
-    std::vector<std::shared_ptr<IEffect>> effects3 = createWithIds(ids);
-    EXPECT_EQ(ids.size(), effects3.size());
+    std::vector<std::shared_ptr<IEffect>> effects = createWithDescs(descs);
+    EXPECT_EQ(descs.size(), effects.size());
+    std::vector<std::shared_ptr<IEffect>> effects2 = createWithDescs(descs);
+    EXPECT_EQ(descs.size(), effects2.size());
+    std::vector<std::shared_ptr<IEffect>> effects3 = createWithDescs(descs);
+    EXPECT_EQ(descs.size(), effects3.size());
 
     destroyEffects(effects);
     destroyEffects(effects2);
@@ -200,28 +202,28 @@
 
 // create and destroy each effect one by one
 TEST_P(EffectFactoryTest, CreateAndDestroyEffectsOneByOne) {
-    std::vector<Descriptor::Identity> ids;
-    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
-    EXPECT_NE(ids.size(), 0UL);
+    std::vector<Descriptor> descs;
+    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
+    EXPECT_NE(descs.size(), 0UL);
 
-    creatAndDestroyIds(ids);
+    creatAndDestroyDescs(descs);
 }
 
 // for each effect: repeat 3 times create and destroy
 TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
-    std::vector<Descriptor::Identity> ids;
-    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
-    EXPECT_NE(ids.size(), 0UL);
+    std::vector<Descriptor> descs;
+    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
+    EXPECT_NE(descs.size(), 0UL);
 
-    creatAndDestroyIds(ids);
-    creatAndDestroyIds(ids);
-    creatAndDestroyIds(ids);
+    creatAndDestroyDescs(descs);
+    creatAndDestroyDescs(descs);
+    creatAndDestroyDescs(descs);
 }
 
 // Expect EX_ILLEGAL_ARGUMENT when create with invalid UUID.
 TEST_P(EffectFactoryTest, CreateWithInvalidUuid) {
-    std::vector<Descriptor::Identity> ids = {kNullDesc, kZeroDesc};
-    auto effects = createWithIds(ids, EX_ILLEGAL_ARGUMENT);
+    std::vector<Descriptor> descs = {kNullDesc, kZeroDesc};
+    auto effects = createWithDescs(descs, EX_ILLEGAL_ARGUMENT);
     EXPECT_EQ(effects.size(), 0UL);
 }
 
@@ -233,23 +235,23 @@
 
 // Same descriptor ID should work after service restart.
 TEST_P(EffectFactoryTest, CreateDestroyWithRestart) {
-    std::vector<Descriptor::Identity> ids;
-    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
-    EXPECT_NE(ids.size(), 0UL);
-    creatAndDestroyIds(ids);
+    std::vector<Descriptor> descs;
+    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
+    EXPECT_NE(descs.size(), 0UL);
+    creatAndDestroyDescs(descs);
 
     mFactoryHelper->RestartFactoryService();
 
     connectAndGetFactory();
-    creatAndDestroyIds(ids);
+    creatAndDestroyDescs(descs);
 }
 
 // Effect handle invalid after restart.
 TEST_P(EffectFactoryTest, EffectInvalidAfterRestart) {
-    std::vector<Descriptor::Identity> ids;
-    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
-    EXPECT_NE(ids.size(), 0UL);
-    std::vector<std::shared_ptr<IEffect>> effects = createWithIds(ids);
+    std::vector<Descriptor> descs;
+    EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
+    EXPECT_NE(descs.size(), 0UL);
+    std::vector<std::shared_ptr<IEffect>> effects = createWithDescs(descs);
 
     ASSERT_NO_FATAL_FAILURE(mFactoryHelper->RestartFactoryService());
 
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index 8212149..4f14bf0 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -752,16 +752,9 @@
         ::testing::Combine(testing::ValuesIn(
                 EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor))),
         [](const testing::TestParamInfo<AudioEffectTest::ParamType>& info) {
-            auto msSinceEpoch = std::chrono::duration_cast<std::chrono::nanoseconds>(
-                                        std::chrono::system_clock::now().time_since_epoch())
-                                        .count();
             auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
-            std::ostringstream address;
-            address << msSinceEpoch << "_factory_" << instance.first.get();
-            std::string name = address.str() + "_UUID_timeLow_" +
-                               ::android::internal::ToString(instance.second.uuid.timeLow) +
-                               "_timeMid_" +
-                               ::android::internal::ToString(instance.second.uuid.timeMid);
+            std::string name = "TYPE_" + instance.second.type.toString() + "_UUID_" +
+                               instance.second.uuid.toString();
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
new file mode 100644
index 0000000..7adf63c
--- /dev/null
+++ b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsHalBassBoostTest"
+
+#include <Utils.h>
+#include <aidl/Vintf.h>
+#include <limits.h>
+
+#include "EffectHelper.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::BassBoost;
+using aidl::android::hardware::audio::effect::Capability;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kBassBoostTypeUUID;
+using aidl::android::hardware::audio::effect::Parameter;
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEffectTargetTest.
+ */
+enum ParamName { PARAM_INSTANCE_NAME, PARAM_STRENGTH };
+using BassBoostParamTestParam =
+        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>, int>;
+
+/*
+ * 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.
+ */
+
+const std::vector<int> kStrengthValues = {
+        std::numeric_limits<int>::min(),
+        BassBoost::MIN_PER_MILLE_STRENGTH - 1,
+        BassBoost::MIN_PER_MILLE_STRENGTH,
+        (BassBoost::MIN_PER_MILLE_STRENGTH + BassBoost::MAX_PER_MILLE_STRENGTH) >> 1,
+        BassBoost::MAX_PER_MILLE_STRENGTH,
+        BassBoost::MAX_PER_MILLE_STRENGTH + 2,
+        std::numeric_limits<int>::max()};
+
+class BassBoostParamTest : public ::testing::TestWithParam<BassBoostParamTestParam>,
+                           public EffectHelper {
+  public:
+    BassBoostParamTest() : mParamStrength(std::get<PARAM_STRENGTH>(GetParam())) {
+        std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+    }
+
+    void SetUp() override {
+        ASSERT_NE(nullptr, mFactory);
+        ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mIdentity));
+
+        Parameter::Specific specific = getDefaultParamSpecific();
+        Parameter::Common common = EffectHelper::createParamCommon(
+                0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+                kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+        IEffect::OpenEffectReturn ret;
+        ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
+        ASSERT_NE(nullptr, mEffect);
+    }
+
+    void TearDown() override {
+        ASSERT_NO_FATAL_FAILURE(close(mEffect));
+        ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+    }
+
+    Parameter::Specific getDefaultParamSpecific() {
+        BassBoost bb = BassBoost::make<BassBoost::strengthPm>(BassBoost::MIN_PER_MILLE_STRENGTH);
+        Parameter::Specific specific =
+                Parameter::Specific::make<Parameter::Specific::bassBoost>(bb);
+        return specific;
+    }
+
+    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+    std::shared_ptr<IFactory> mFactory;
+    std::shared_ptr<IEffect> mEffect;
+    Descriptor::Identity mIdentity;
+    int mParamStrength = BassBoost::MIN_PER_MILLE_STRENGTH;
+
+    void SetAndGetBassBoostParameters() {
+        for (auto& it : mTags) {
+            auto& tag = it.first;
+            auto& bb = it.second;
+
+            // validate parameter
+            Descriptor desc;
+            ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
+            const bool valid = isTagInRange(it.first, it.second, desc);
+            const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+            // set parameter
+            Parameter expectParam;
+            Parameter::Specific specific;
+            specific.set<Parameter::Specific::bassBoost>(bb);
+            expectParam.set<Parameter::specific>(specific);
+            EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString();
+
+            // only get if parameter in range and set success
+            if (expected == EX_NONE) {
+                Parameter getParam;
+                Parameter::Id id;
+                BassBoost::Id bbId;
+                bbId.set<BassBoost::Id::commonTag>(tag);
+                id.set<Parameter::Id::bassBoostTag>(bbId);
+                // if set success, then get should match
+                EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam));
+                EXPECT_EQ(expectParam, getParam);
+            }
+        }
+    }
+
+    void addStrengthParam(int strength) {
+        BassBoost bb;
+        bb.set<BassBoost::strengthPm>(strength);
+        mTags.push_back({BassBoost::strengthPm, bb});
+    }
+
+    bool isTagInRange(const BassBoost::Tag& tag, const BassBoost& bb,
+                      const Descriptor& desc) const {
+        const BassBoost::Capability& bbCap = desc.capability.get<Capability::bassBoost>();
+        switch (tag) {
+            case BassBoost::strengthPm: {
+                int strength = bb.get<BassBoost::strengthPm>();
+                return isStrengthInRange(bbCap, strength);
+            }
+            default:
+                return false;
+        }
+        return false;
+    }
+
+    bool isStrengthInRange(const BassBoost::Capability& cap, int strength) const {
+        return cap.strengthSupported && strength >= BassBoost::MIN_PER_MILLE_STRENGTH &&
+               strength <= BassBoost::MAX_PER_MILLE_STRENGTH;
+    }
+
+  private:
+    std::vector<std::pair<BassBoost::Tag, BassBoost>> mTags;
+    void CleanUp() { mTags.clear(); }
+};
+
+TEST_P(BassBoostParamTest, SetAndGetStrength) {
+    EXPECT_NO_FATAL_FAILURE(addStrengthParam(mParamStrength));
+    SetAndGetBassBoostParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        BassBoostTest, BassBoostParamTest,
+        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+                                   IFactory::descriptor, kBassBoostTypeUUID)),
+                           testing::ValuesIn(kStrengthValues)),
+        [](const testing::TestParamInfo<BassBoostParamTest::ParamType>& info) {
+            auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
+            std::string strength = std::to_string(std::get<PARAM_STRENGTH>(info.param));
+            std::string name = instance.second.uuid.toString() + "_strength_" + strength;
+            std::replace_if(
+                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+            return name;
+        });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BassBoostParamTest);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
index f19dff6..1b147a6 100644
--- a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
@@ -327,18 +327,9 @@
                                    IFactory::descriptor, kEqualizerTypeUUID)),
                            testing::ValuesIn(kBandLevels)),
         [](const testing::TestParamInfo<EqualizerTest::ParamType>& info) {
-            auto msSinceEpoch = std::chrono::duration_cast<std::chrono::nanoseconds>(
-                                        std::chrono::system_clock::now().time_since_epoch())
-                                        .count();
             auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
             std::string bandLevel = std::to_string(std::get<PARAM_BAND_LEVEL>(info.param));
-            std::ostringstream address;
-            address << msSinceEpoch << "_factory_" << instance.first.get();
-            std::string name = address.str() + "_UUID_timeLow_" +
-                               ::android::internal::ToString(instance.second.uuid.timeLow) +
-                               "_timeMid_" +
-                               ::android::internal::ToString(instance.second.uuid.timeMid) +
-                               "_bandLevel_" + bandLevel;
+            std::string name = instance.second.uuid.toString() + "_bandLevel_" + bandLevel;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
index 1485657..3fd2812 100644
--- a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <aidl/Vintf.h>
+#include <string>
 
 #define LOG_TAG "VtsHalLoudnessEnhancerTest"
 
@@ -129,19 +130,9 @@
                                    IFactory::descriptor, kLoudnessEnhancerTypeUUID)),
                            testing::ValuesIn(kGainMbValues)),
         [](const testing::TestParamInfo<LoudnessEnhancerParamTest::ParamType>& info) {
-            auto msSinceEpoch = std::chrono::duration_cast<std::chrono::nanoseconds>(
-                                        std::chrono::system_clock::now().time_since_epoch())
-                                        .count();
             auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
             std::string gainMb = std::to_string(std::get<PARAM_GAIN_MB>(info.param));
-
-            std::ostringstream address;
-            address << msSinceEpoch << "_factory_" << instance.first.get();
-            std::string name = address.str() + "_UUID_timeLow_" +
-                               ::android::internal::ToString(instance.second.uuid.timeLow) +
-                               "_timeMid_" +
-                               ::android::internal::ToString(instance.second.uuid.timeMid) +
-                               "_gainMb" + gainMb;
+            std::string name = instance.second.uuid.toString() + "_gainMb_" + gainMb;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/automotive/can/aidl/Android.bp b/automotive/can/aidl/Android.bp
new file mode 100644
index 0000000..67333b9
--- /dev/null
+++ b/automotive/can/aidl/Android.bp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+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.automotive.can",
+    vendor_available: true,
+    srcs: ["android/hardware/automotive/can/*.aidl"],
+    stability: "vintf",
+    host_supported: true,
+    backend: {
+        java: {
+            enabled: false,
+        },
+        rust: {
+            enabled: true,
+        },
+    },
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/BusConfig.aidl
similarity index 76%
copy from audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
copy to automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/BusConfig.aidl
index 8ad4848..0212e00 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
+++ b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/BusConfig.aidl
@@ -31,27 +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.audio.effect;
+package android.hardware.automotive.can;
 @VintfStability
-union Reverb {
-  android.hardware.audio.effect.VendorExtension vendor;
-  int roomLevelMb;
-  int roomHfLevelMb;
-  int decayTimeMs;
-  int decayHfRatioPm;
-  int levelMb;
-  int delayMs;
-  int diffusionPm;
-  int densityPm;
-  boolean bypass;
-  @VintfStability
-  union Id {
-    int vendorExtensionTag;
-    android.hardware.audio.effect.Reverb.Tag commonTag;
-  }
-  @VintfStability
-  parcelable Capability {
-    android.hardware.audio.effect.VendorExtension extension;
-    int maxDecayTimeMs;
+parcelable BusConfig {
+  String name;
+  android.hardware.automotive.can.BusConfig.InterfaceId interfaceId;
+  int bitrate;
+  union InterfaceId {
+    android.hardware.automotive.can.VirtualInterface virtualif;
+    android.hardware.automotive.can.NativeInterface nativeif;
+    android.hardware.automotive.can.SlcanInterface slcan;
+    android.hardware.automotive.can.IndexedInterface indexed;
   }
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/ICanController.aidl
similarity index 75%
copy from audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
copy to automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/ICanController.aidl
index 8ad4848..5d032f2 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
+++ b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/ICanController.aidl
@@ -31,27 +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.audio.effect;
+package android.hardware.automotive.can;
 @VintfStability
-union Reverb {
-  android.hardware.audio.effect.VendorExtension vendor;
-  int roomLevelMb;
-  int roomHfLevelMb;
-  int decayTimeMs;
-  int decayHfRatioPm;
-  int levelMb;
-  int delayMs;
-  int diffusionPm;
-  int densityPm;
-  boolean bypass;
-  @VintfStability
-  union Id {
-    int vendorExtensionTag;
-    android.hardware.audio.effect.Reverb.Tag commonTag;
-  }
-  @VintfStability
-  parcelable Capability {
-    android.hardware.audio.effect.VendorExtension extension;
-    int maxDecayTimeMs;
-  }
+interface ICanController {
+  android.hardware.automotive.can.InterfaceType[] getSupportedInterfaceTypes();
+  String getInterfaceName(in String busName);
+  String upBus(in android.hardware.automotive.can.BusConfig config);
+  void downBus(in String name);
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/IndexedInterface.aidl
similarity index 75%
copy from audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
copy to automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/IndexedInterface.aidl
index 8ad4848..1b00adf 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
+++ b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/IndexedInterface.aidl
@@ -31,27 +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.audio.effect;
+package android.hardware.automotive.can;
 @VintfStability
-union Reverb {
-  android.hardware.audio.effect.VendorExtension vendor;
-  int roomLevelMb;
-  int roomHfLevelMb;
-  int decayTimeMs;
-  int decayHfRatioPm;
-  int levelMb;
-  int delayMs;
-  int diffusionPm;
-  int densityPm;
-  boolean bypass;
-  @VintfStability
-  union Id {
-    int vendorExtensionTag;
-    android.hardware.audio.effect.Reverb.Tag commonTag;
-  }
-  @VintfStability
-  parcelable Capability {
-    android.hardware.audio.effect.VendorExtension extension;
-    int maxDecayTimeMs;
-  }
+parcelable IndexedInterface {
+  byte index;
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/InterfaceType.aidl
similarity index 75%
copy from audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
copy to automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/InterfaceType.aidl
index 8ad4848..44865aa 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
+++ b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/InterfaceType.aidl
@@ -31,27 +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.audio.effect;
-@VintfStability
-union Reverb {
-  android.hardware.audio.effect.VendorExtension vendor;
-  int roomLevelMb;
-  int roomHfLevelMb;
-  int decayTimeMs;
-  int decayHfRatioPm;
-  int levelMb;
-  int delayMs;
-  int diffusionPm;
-  int densityPm;
-  boolean bypass;
-  @VintfStability
-  union Id {
-    int vendorExtensionTag;
-    android.hardware.audio.effect.Reverb.Tag commonTag;
-  }
-  @VintfStability
-  parcelable Capability {
-    android.hardware.audio.effect.VendorExtension extension;
-    int maxDecayTimeMs;
-  }
+package android.hardware.automotive.can;
+@Backing(type="byte") @VintfStability
+enum InterfaceType {
+  VIRTUAL = 0,
+  NATIVE = 1,
+  SLCAN = 2,
+  INDEXED = 3,
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/NativeInterface.aidl
similarity index 76%
copy from audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
copy to automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/NativeInterface.aidl
index 8ad4848..5d6c119 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
+++ b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/NativeInterface.aidl
@@ -31,27 +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.audio.effect;
+package android.hardware.automotive.can;
 @VintfStability
-union Reverb {
-  android.hardware.audio.effect.VendorExtension vendor;
-  int roomLevelMb;
-  int roomHfLevelMb;
-  int decayTimeMs;
-  int decayHfRatioPm;
-  int levelMb;
-  int delayMs;
-  int diffusionPm;
-  int densityPm;
-  boolean bypass;
-  @VintfStability
-  union Id {
-    int vendorExtensionTag;
-    android.hardware.audio.effect.Reverb.Tag commonTag;
-  }
-  @VintfStability
-  parcelable Capability {
-    android.hardware.audio.effect.VendorExtension extension;
-    int maxDecayTimeMs;
+parcelable NativeInterface {
+  android.hardware.automotive.can.NativeInterface.InterfaceId interfaceId;
+  union InterfaceId {
+    String ifname;
+    String[] serialno;
   }
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/Result.aidl
similarity index 75%
copy from audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
copy to automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/Result.aidl
index 8ad4848..010792a 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
+++ b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/Result.aidl
@@ -31,27 +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.audio.effect;
-@VintfStability
-union Reverb {
-  android.hardware.audio.effect.VendorExtension vendor;
-  int roomLevelMb;
-  int roomHfLevelMb;
-  int decayTimeMs;
-  int decayHfRatioPm;
-  int levelMb;
-  int delayMs;
-  int diffusionPm;
-  int densityPm;
-  boolean bypass;
-  @VintfStability
-  union Id {
-    int vendorExtensionTag;
-    android.hardware.audio.effect.Reverb.Tag commonTag;
-  }
-  @VintfStability
-  parcelable Capability {
-    android.hardware.audio.effect.VendorExtension extension;
-    int maxDecayTimeMs;
-  }
+package android.hardware.automotive.can;
+@Backing(type="int") @VintfStability
+enum Result {
+  OK = 0,
+  UNKNOWN_ERROR = 1,
+  INVALID_STATE = 2,
+  NOT_SUPPORTED = 3,
+  BAD_INTERFACE_ID = 4,
+  BAD_BITRATE = 5,
+  BAD_BUS_NAME = 6,
+  INTERFACE_DOWN = 7,
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/SlcanInterface.aidl
similarity index 76%
copy from audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
copy to automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/SlcanInterface.aidl
index 8ad4848..af0c07d 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
+++ b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/SlcanInterface.aidl
@@ -31,27 +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.audio.effect;
+package android.hardware.automotive.can;
 @VintfStability
-union Reverb {
-  android.hardware.audio.effect.VendorExtension vendor;
-  int roomLevelMb;
-  int roomHfLevelMb;
-  int decayTimeMs;
-  int decayHfRatioPm;
-  int levelMb;
-  int delayMs;
-  int diffusionPm;
-  int densityPm;
-  boolean bypass;
-  @VintfStability
-  union Id {
-    int vendorExtensionTag;
-    android.hardware.audio.effect.Reverb.Tag commonTag;
-  }
-  @VintfStability
-  parcelable Capability {
-    android.hardware.audio.effect.VendorExtension extension;
-    int maxDecayTimeMs;
+parcelable SlcanInterface {
+  android.hardware.automotive.can.SlcanInterface.InterfaceId interfaceId;
+  union InterfaceId {
+    String ttyname;
+    String[] serialno;
   }
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/VirtualInterface.aidl
similarity index 75%
copy from audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
copy to automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/VirtualInterface.aidl
index 8ad4848..c870612 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
+++ b/automotive/can/aidl/aidl_api/android.hardware.automotive.can/current/android/hardware/automotive/can/VirtualInterface.aidl
@@ -31,27 +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.audio.effect;
+package android.hardware.automotive.can;
 @VintfStability
-union Reverb {
-  android.hardware.audio.effect.VendorExtension vendor;
-  int roomLevelMb;
-  int roomHfLevelMb;
-  int decayTimeMs;
-  int decayHfRatioPm;
-  int levelMb;
-  int delayMs;
-  int diffusionPm;
-  int densityPm;
-  boolean bypass;
-  @VintfStability
-  union Id {
-    int vendorExtensionTag;
-    android.hardware.audio.effect.Reverb.Tag commonTag;
-  }
-  @VintfStability
-  parcelable Capability {
-    android.hardware.audio.effect.VendorExtension extension;
-    int maxDecayTimeMs;
-  }
+parcelable VirtualInterface {
+  String ifname;
 }
diff --git a/automotive/can/aidl/android/hardware/automotive/can/BusConfig.aidl b/automotive/can/aidl/android/hardware/automotive/can/BusConfig.aidl
new file mode 100644
index 0000000..4e1027b
--- /dev/null
+++ b/automotive/can/aidl/android/hardware/automotive/can/BusConfig.aidl
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.automotive.can;
+
+import android.hardware.automotive.can.IndexedInterface;
+import android.hardware.automotive.can.NativeInterface;
+import android.hardware.automotive.can.SlcanInterface;
+import android.hardware.automotive.can.VirtualInterface;
+
+/**
+ * Configuration of the (physical or virtual) CAN bus.
+ *
+ * ISO TP and CAN FD support is dependent upon the hardware.
+ */
+@VintfStability
+parcelable BusConfig {
+    /**
+     * Name by which a given bus may be referenced.
+     *
+     * It must consist of only alphanumeric characters and underscore
+     * (a-z, A-Z, 0-9, '_'), at least 1 and at most 32 characters long.
+     *
+     * This field is *not* meant to distinguish between hardware interfaces
+     * nor preselect parameters like bitrate.
+     *
+     * This field represents a more human-friendly name for a CAN bus:
+     * e.x. rather than /some/dev/can1234, "name" might be "BodyCAN" or "CCAN"
+     */
+    String name;
+
+    /**
+     * Hardware interface configuration.
+     *
+     * This union's discriminator has an equivalent enum {@see InterfaceType} to
+     * express compatibility via getSupportedInterfaceTypes().
+     */
+    union InterfaceId {
+        /** Virtual SocketCAN interface. */
+        VirtualInterface virtualif;
+
+        /** Native SocketCAN interface. */
+        NativeInterface nativeif;
+
+        /** Serial line CAN interface. */
+        SlcanInterface slcan;
+
+        /**
+         * Proprietary, device-specific interface.
+         *
+         * Non-SocketCAN interfaces should use this variant.
+         */
+        IndexedInterface indexed;
+    }
+
+    InterfaceId interfaceId;
+
+    /**
+     * Bit rate for CAN communication.
+     *
+     * Typical bit rates are: 100000, 125000, 250000, 500000.
+     *
+     * For {@see interfaceId#virtual} interfaces, this value is ignored.
+     */
+    int bitrate;
+}
diff --git a/automotive/can/aidl/android/hardware/automotive/can/ICanController.aidl b/automotive/can/aidl/android/hardware/automotive/can/ICanController.aidl
new file mode 100644
index 0000000..97c2674
--- /dev/null
+++ b/automotive/can/aidl/android/hardware/automotive/can/ICanController.aidl
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.automotive.can;
+
+import android.hardware.automotive.can.BusConfig;
+import android.hardware.automotive.can.InterfaceType;
+import android.hardware.automotive.can.Result;
+
+/**
+ * Represents a CAN controller that's capable of configuring CAN bus interfaces.
+ *
+ * The goal of this service is to configure and manage CAN interfaces.
+ *
+ * Providing an ICanController interface to configure CAN buses is optional.
+ * A system can elect to configure CAN buses manually if the hardware is
+ * dedicated to a specific application.
+ */
+@VintfStability
+interface ICanController {
+    /**
+     * Fetches the list of interface types supported by this HAL server.
+     *
+     * @return iftypes The list of supported interface types.
+     */
+    InterfaceType[] getSupportedInterfaceTypes();
+
+    /**
+     * Gets the interface name given the name of the bus. This will
+     *
+     * @param busName Name of the CAN bus who's interface name we would like
+     * (e.x. BCAN, CCAN, HS3, BodyCAN, ...)
+     * @return name of the socketcan network interface corresponding to busName
+     * (e.x. can0, vcan5, ...)
+     */
+    String getInterfaceName(in String busName);
+
+    /**
+     * Bring up a CAN bus.
+     *
+     * @param config Configuration for the CAN bus.
+     * @return name of iface if successful
+     */
+    String upBus(in BusConfig config);
+
+    /**
+     * Bring down a CAN bus.
+     *
+     * @param name Name of the bus (@see BusConfig#name} to bring down.
+     */
+    void downBus(in String name);
+}
diff --git a/automotive/can/aidl/android/hardware/automotive/can/IndexedInterface.aidl b/automotive/can/aidl/android/hardware/automotive/can/IndexedInterface.aidl
new file mode 100644
index 0000000..13e223f
--- /dev/null
+++ b/automotive/can/aidl/android/hardware/automotive/can/IndexedInterface.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.automotive.can;
+
+@VintfStability
+parcelable IndexedInterface {
+    /** Interface number, 0-based. */
+    byte index;
+}
diff --git a/automotive/can/aidl/android/hardware/automotive/can/InterfaceType.aidl b/automotive/can/aidl/android/hardware/automotive/can/InterfaceType.aidl
new file mode 100644
index 0000000..b13648a
--- /dev/null
+++ b/automotive/can/aidl/android/hardware/automotive/can/InterfaceType.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.automotive.can;
+
+/**
+ * Type of an interface, an equivalent to BusConfig::InterfaceId
+ * union discriminator. Defines a number of specific standard hardware
+ * families and a generic catch-all type of {@see INDEXED}.
+ */
+@VintfStability
+@Backing(type="byte")
+enum InterfaceType {
+    /** Virtual SocketCAN interface. */
+    VIRTUAL,
+
+    /** Native SocketCAN interface. */
+    NATIVE,
+
+    /** Serial line CAN interface. */
+    SLCAN,
+
+    /** Proprietary, device-specific interface. */
+    INDEXED,
+}
diff --git a/automotive/can/aidl/android/hardware/automotive/can/NativeInterface.aidl b/automotive/can/aidl/android/hardware/automotive/can/NativeInterface.aidl
new file mode 100644
index 0000000..30c24c3
--- /dev/null
+++ b/automotive/can/aidl/android/hardware/automotive/can/NativeInterface.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.automotive.can;
+
+@VintfStability
+parcelable NativeInterface {
+    union InterfaceId {
+        /** Interface name, such as can0. */
+        String ifname;
+
+        /**
+         * Alternatively to providing {@see ifname}, one may provide a list of
+         * interface serial number suffixes. If there happens to be a device
+         * (like USB2CAN) with a matching serial number suffix, the HAL service
+         * will locate it.
+         *
+         * Client may utilize this in two ways: by matching against the
+         * entire serial number, or the last few characters (usually
+         * one). The former is better for small-scale test deployments
+         * (with just a handful of vehicles), the latter is good for
+         * larger scale (where a small suffix list may support large
+         * test fleet).
+         */
+        String[] serialno;
+    }
+
+    InterfaceId interfaceId;
+}
diff --git a/automotive/can/aidl/android/hardware/automotive/can/Result.aidl b/automotive/can/aidl/android/hardware/automotive/can/Result.aidl
new file mode 100644
index 0000000..cdd0066
--- /dev/null
+++ b/automotive/can/aidl/android/hardware/automotive/can/Result.aidl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.automotive.can;
+
+/**
+ * Possible error codes (or OK) for ICanController.
+ */
+@VintfStability
+@Backing(type="int")
+enum Result {
+    OK,
+
+    /**
+     * General error class, if others are not applicable.
+     */
+    UNKNOWN_ERROR,
+
+    /**
+     * Up request was called out of order (i.e. trying to up the interface
+     * twice).
+     */
+    INVALID_STATE,
+
+    /** Interface type is not supported. */
+    NOT_SUPPORTED,
+
+    /**
+     * Provided interface ID (index, name, device path) doesn't exist or there
+     * is no device with a given serial number.
+     */
+    BAD_INTERFACE_ID,
+
+    /** Provided bit rate is not supported by the hardware. */
+    BAD_BITRATE,
+
+    /**
+     * Provided bus name ({@see BusConfig#name}) has invalid format or doesn't exist.
+     */
+    BAD_BUS_NAME,
+
+    /**
+     * The interface for the bus you are trying to interact with is currently
+     * down. As opposed to INVALID_STATE, this serves to warn the caller
+     * _before_ they attempt an invalid operation.
+     */
+    INTERFACE_DOWN,
+}
diff --git a/automotive/can/aidl/android/hardware/automotive/can/SlcanInterface.aidl b/automotive/can/aidl/android/hardware/automotive/can/SlcanInterface.aidl
new file mode 100644
index 0000000..4ed8583
--- /dev/null
+++ b/automotive/can/aidl/android/hardware/automotive/can/SlcanInterface.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.automotive.can;
+
+@VintfStability
+parcelable SlcanInterface {
+    union InterfaceId {
+        /** Path to a device, such as /dev/ttyUSB0. */
+        String ttyname;
+
+        /**
+         * List of interface serial number suffixes.
+         * {@see Socketcan::serialno}
+         */
+        String[] serialno;
+    }
+
+    InterfaceId interfaceId;
+}
diff --git a/automotive/can/aidl/android/hardware/automotive/can/VirtualInterface.aidl b/automotive/can/aidl/android/hardware/automotive/can/VirtualInterface.aidl
new file mode 100644
index 0000000..7e1e5e1
--- /dev/null
+++ b/automotive/can/aidl/android/hardware/automotive/can/VirtualInterface.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.automotive.can;
+
+@VintfStability
+parcelable VirtualInterface {
+    /**
+     * Interface name, such as vcan0. If the interface doesn't
+     * exist, HAL server must create it.
+     */
+    String ifname;
+}
diff --git a/automotive/can/aidl/default/Android.bp b/automotive/can/aidl/default/Android.bp
new file mode 100644
index 0000000..d44cb91
--- /dev/null
+++ b/automotive/can/aidl/default/Android.bp
@@ -0,0 +1,51 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_binary {
+    name: "android.hardware.automotive.can-service",
+    init_rc: ["android.hardware.automotive.can.rc"],
+    defaults: ["android.hardware.automotive.can@defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: [
+        "CanBus.cpp",
+        "CanBusSlcan.cpp",
+        "CanBusNative.cpp",
+        "CanBusVirtual.cpp",
+        "CanController.cpp",
+        "service.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.automotive.can-V1-ndk",
+        "libbase",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.automotive.can@libnetdevice",
+        "android.hardware.automotive@libc++fs",
+        "libnl++",
+    ],
+    vintf_fragments: ["android.hardware.automotive.can.xml"],
+}
diff --git a/automotive/can/aidl/default/CanBus.cpp b/automotive/can/aidl/default/CanBus.cpp
new file mode 100644
index 0000000..d1f9b78
--- /dev/null
+++ b/automotive/can/aidl/default/CanBus.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CanBus.h"
+
+#include <android-base/logging.h>
+#include <libnetdevice/libnetdevice.h>
+
+namespace aidl::android::hardware::automotive::can {
+
+CanBus::CanBus(std::string_view ifname) : mIfname(ifname) {}
+
+CanBus::~CanBus() {
+    std::lock_guard<std::mutex> lck(mIsUpGuard);
+    CHECK(!mIsUp) << "Interface is still up while being destroyed";
+}
+
+Result CanBus::preUp() {
+    return Result::OK;
+}
+
+bool CanBus::postDown() {
+    return true;
+}
+
+std::string CanBus::getIfaceName() {
+    return mIfname;
+}
+
+Result CanBus::up() {
+    std::lock_guard<std::mutex> lck(mIsUpGuard);
+
+    if (mIsUp) {
+        LOG(WARNING) << "Interface is already up";
+        return Result::INVALID_STATE;
+    }
+
+    const auto preResult = preUp();
+    if (preResult != Result::OK) return preResult;
+
+    const auto isUp = ::android::netdevice::isUp(mIfname);
+    if (!isUp.has_value()) {
+        // preUp() should prepare the interface (either create or make sure it's there)
+        LOG(ERROR) << "Interface " << mIfname << " didn't get prepared";
+        return Result::BAD_INTERFACE_ID;
+    }
+
+    if (!*isUp && !::android::netdevice::up(mIfname)) {
+        LOG(ERROR) << "Can't bring " << mIfname << " up";
+        return Result::UNKNOWN_ERROR;
+    }
+    mDownAfterUse = !*isUp;
+
+    mIsUp = true;
+    return Result::OK;
+}
+
+Result CanBus::down() {
+    std::lock_guard<std::mutex> lck(mIsUpGuard);
+
+    if (!mIsUp) {
+        LOG(WARNING) << "Interface is already down";
+        return Result::INVALID_STATE;
+    }
+    mIsUp = false;
+
+    Result success = Result::OK;
+
+    if (mDownAfterUse && !::android::netdevice::down(mIfname)) {
+        LOG(ERROR) << "Can't bring " << mIfname << " down";
+        // don't return yet, let's try to do best-effort cleanup
+        success = Result::UNKNOWN_ERROR;
+    }
+
+    if (!postDown()) success = Result::UNKNOWN_ERROR;
+
+    return success;
+}
+
+}  // namespace aidl::android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/CanBus.h b/automotive/can/aidl/default/CanBus.h
new file mode 100644
index 0000000..abdbe51
--- /dev/null
+++ b/automotive/can/aidl/default/CanBus.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/automotive/can/Result.h>
+
+#include <android-base/macros.h>
+#include <utils/Mutex.h>
+
+#include <atomic>
+#include <mutex>
+
+namespace aidl::android::hardware::automotive::can {
+
+class CanBus {
+  public:
+    /**
+     * Some interface types (such as SLCAN) don't get an interface name until after being
+     * initialized, hence ifname is optional.
+     *
+     * You MUST ensure mIfname is initialized prior to the completion of preUp().
+     */
+    CanBus(std::string_view ifname = std::string_view{""});
+
+    virtual ~CanBus();
+
+    Result up();
+    Result down();
+    std::string getIfaceName();
+
+  protected:
+    /**
+     * Prepare the SocketCAN interface.
+     *
+     * After calling this method, mIfname network interface is available and ready to be brought up.
+     *
+     * \return true upon success and false upon failure
+     */
+    virtual Result preUp();
+
+    /**
+     * Cleanup after bringing the interface down.
+     *
+     * This is a counterpart to preUp().
+     *
+     * \return true upon success and false upon failure
+     */
+    virtual bool postDown();
+
+    /** Network interface name. */
+    std::string mIfname;
+
+  private:
+    /**
+     * Guard for up flag is required to be held for entire time when the interface is being used
+     * because we don't want the interface to be torn down while executing that operation.
+     */
+    std::mutex mIsUpGuard;
+    bool mIsUp GUARDED_BY(mIsUpGuard) = false;
+
+    bool mDownAfterUse;
+};
+
+}  // namespace aidl::android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/CanBusNative.cpp b/automotive/can/aidl/default/CanBusNative.cpp
new file mode 100644
index 0000000..8a7de99
--- /dev/null
+++ b/automotive/can/aidl/default/CanBusNative.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CanBusNative.h"
+
+#include <android-base/logging.h>
+#include <libnetdevice/can.h>
+#include <libnetdevice/libnetdevice.h>
+
+namespace aidl::android::hardware::automotive::can {
+
+using namespace ::android;
+
+CanBusNative::CanBusNative(const std::string& ifname, uint32_t bitrate)
+    : CanBus(ifname), mBitrate(bitrate) {}
+
+Result CanBusNative::preUp() {
+    if (!netdevice::exists(mIfname)) {
+        LOG(ERROR) << "Interface " << mIfname << " doesn't exist";
+        return Result::BAD_INTERFACE_ID;
+    }
+
+    if (mBitrate == 0) {
+        // interface is already up and we just want to register it
+        return Result::OK;
+    }
+
+    if (!netdevice::down(mIfname)) {
+        LOG(ERROR) << "Can't bring " << mIfname << " down (to configure it)";
+        return Result::UNKNOWN_ERROR;
+    }
+
+    if (!netdevice::can::setBitrate(mIfname, mBitrate)) {
+        LOG(ERROR) << "Can't set bitrate " << mBitrate << " for " << mIfname;
+        return Result::BAD_BITRATE;
+    }
+
+    return Result::OK;
+}
+
+}  // namespace aidl::android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/CanBusNative.h b/automotive/can/aidl/default/CanBusNative.h
new file mode 100644
index 0000000..32846c7
--- /dev/null
+++ b/automotive/can/aidl/default/CanBusNative.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "CanBus.h"
+
+namespace aidl::android::hardware::automotive::can {
+
+class CanBusNative : public CanBus {
+  public:
+    CanBusNative(const std::string& ifname, uint32_t bitrate);
+
+  protected:
+    virtual Result preUp() override;
+
+  private:
+    const uint32_t mBitrate;
+};
+
+}  // namespace aidl::android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/CanBusSlcan.cpp b/automotive/can/aidl/default/CanBusSlcan.cpp
new file mode 100644
index 0000000..6060419
--- /dev/null
+++ b/automotive/can/aidl/default/CanBusSlcan.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CanBusSlcan.h"
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <libnetdevice/libnetdevice.h>
+
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <net/if.h>
+#include <termios.h>
+
+#include <map>
+
+namespace aidl::android::hardware::automotive::can {
+
+using namespace std::string_view_literals;
+using namespace ::android::base;
+
+namespace slcanprotocol {
+static constexpr std::string_view kOpenCommand = "O\r"sv;
+static constexpr std::string_view kCloseCommand = "C\r"sv;
+static constexpr int kSlcanDiscipline = N_SLCAN;
+static constexpr int kDefaultDiscipline = N_TTY;
+
+static const std::map<uint32_t, std::string_view> kBitrateCommands = {
+        {10000, "C\rS0\r"sv},  {20000, "C\rS1\r"sv},  {50000, "C\rS2\r"sv},
+        {100000, "C\rS3\r"sv}, {125000, "C\rS4\r"sv}, {250000, "C\rS5\r"sv},
+        {500000, "C\rS6\r"sv}, {800000, "C\rS7\r"sv}, {1000000, "C\rS8\r"sv}};
+}  // namespace slcanprotocol
+
+/**
+ * Serial Line CAN constructor
+ * \param string uartName - name of slcan device (e.x. /dev/ttyUSB0)
+ * \param uint32_t bitrate - speed of the CAN bus (125k = MSCAN, 500k = HSCAN)
+ */
+CanBusSlcan::CanBusSlcan(const std::string& uartName, uint32_t bitrate)
+    : CanBus(), mTtyPath(uartName), kBitrate(bitrate) {}
+
+/** helper function to update CanBusSlcan object's iface name */
+Result CanBusSlcan::updateIfaceName(unique_fd& uartFd) {
+    struct ifreq ifrequest = {};
+    /*
+     * Fetching the iface name with an ioctl won't interfere with an open socketCAN iface attached
+     * to this tty. This is important in the event we are trying to register a SLCAN based iface
+     * that has already been configured and brought up.
+     */
+    if (ioctl(uartFd.get(), SIOCGIFNAME, ifrequest.ifr_name) < 0) {
+        PLOG(ERROR) << "Failed to get the name of the created device";
+        return Result::UNKNOWN_ERROR;
+    }
+
+    // Update the CanBus object with name that was assigned to it
+    mIfname = ifrequest.ifr_name;
+    return Result::OK;
+}
+
+Result CanBusSlcan::preUp() {
+    // verify valid bitrate and translate to serial command format
+    std::optional<std::string_view> canBitrateCommand = std::nullopt;
+    if (kBitrate != 0) {
+        const auto lookupIt = slcanprotocol::kBitrateCommands.find(kBitrate);
+        if (lookupIt == slcanprotocol::kBitrateCommands.end()) {
+            return Result::BAD_BITRATE;
+        }
+        canBitrateCommand = lookupIt->second;
+    }
+
+    /* Attempt to open the uart in r/w without blocking or becoming the
+     * controlling terminal */
+    mFd = unique_fd(open(mTtyPath.c_str(), O_RDWR | O_NONBLOCK | O_NOCTTY | O_CLOEXEC));
+    if (!mFd.ok()) {
+        PLOG(ERROR) << "SLCAN Failed to open " << mTtyPath;
+        return Result::BAD_INTERFACE_ID;
+    }
+
+    // If the device is already up, update the iface name in our CanBusSlcan object
+    if (kBitrate == 0) {
+        return updateIfaceName(mFd);
+    }
+
+    // blank terminal settings and pull them from the device
+    struct termios terminalSettings = {};
+    if (tcgetattr(mFd.get(), &terminalSettings) < 0) {
+        PLOG(ERROR) << "Failed to read attrs of" << mTtyPath;
+        return Result::UNKNOWN_ERROR;
+    }
+
+    // change settings to raw mode
+    cfmakeraw(&terminalSettings);
+
+    // disable software flow control
+    terminalSettings.c_iflag &= ~IXOFF;
+    // enable hardware flow control
+    terminalSettings.c_cflag |= CRTSCTS;
+
+    struct serial_struct serialSettings;
+    // get serial settings
+    if (ioctl(mFd.get(), TIOCGSERIAL, &serialSettings) < 0) {
+        PLOG(ERROR) << "Failed to read serial settings from " << mTtyPath;
+        return Result::UNKNOWN_ERROR;
+    }
+    // set low latency mode
+    serialSettings.flags |= ASYNC_LOW_LATENCY;
+    // apply serial settings
+    if (ioctl(mFd.get(), TIOCSSERIAL, &serialSettings) < 0) {
+        PLOG(ERROR) << "Failed to set low latency mode on " << mTtyPath;
+        return Result::UNKNOWN_ERROR;
+    }
+
+    /* TCSADRAIN applies settings after we finish writing the rest of our
+     * changes (as opposed to TCSANOW, which changes immediately) */
+    if (tcsetattr(mFd.get(), TCSADRAIN, &terminalSettings) < 0) {
+        PLOG(ERROR) << "Failed to apply terminal settings to " << mTtyPath;
+        return Result::UNKNOWN_ERROR;
+    }
+
+    // apply speed setting for CAN
+    if (!WriteStringToFd(*canBitrateCommand, mFd)) {
+        PLOG(ERROR) << "Failed to apply CAN bitrate";
+        return Result::UNKNOWN_ERROR;
+    }
+
+    // TODO(b/144775286): set open flag & support listen only
+    if (!WriteStringToFd(slcanprotocol::kOpenCommand, mFd)) {
+        PLOG(ERROR) << "Failed to set open flag";
+        return Result::UNKNOWN_ERROR;
+    }
+
+    // set line discipline to slcan
+    if (ioctl(mFd.get(), TIOCSETD, &slcanprotocol::kSlcanDiscipline) < 0) {
+        PLOG(ERROR) << "Failed to set line discipline to slcan";
+        return Result::UNKNOWN_ERROR;
+    }
+
+    // Update the CanBus object with name that was assigned to it
+    return updateIfaceName(mFd);
+}
+
+bool CanBusSlcan::postDown() {
+    // reset the line discipline to TTY mode
+    if (ioctl(mFd.get(), TIOCSETD, &slcanprotocol::kDefaultDiscipline) < 0) {
+        LOG(ERROR) << "Failed to reset line discipline!";
+        return false;
+    }
+
+    // issue the close command
+    if (!WriteStringToFd(slcanprotocol::kCloseCommand, mFd)) {
+        LOG(ERROR) << "Failed to close tty!";
+        return false;
+    }
+
+    // close our unique_fd
+    mFd.reset();
+
+    return true;
+}
+
+}  // namespace aidl::android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/CanBusSlcan.h b/automotive/can/aidl/default/CanBusSlcan.h
new file mode 100644
index 0000000..a1c908c
--- /dev/null
+++ b/automotive/can/aidl/default/CanBusSlcan.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "CanBus.h"
+
+#include <android-base/unique_fd.h>
+
+namespace aidl::android::hardware::automotive::can {
+
+class CanBusSlcan : public CanBus {
+  public:
+    CanBusSlcan(const std::string& uartName, uint32_t bitrate);
+
+  protected:
+    virtual Result preUp() override;
+    virtual bool postDown() override;
+
+  private:
+    Result updateIfaceName(::android::base::unique_fd& uartFd);
+
+    const std::string mTtyPath;
+    const uint32_t kBitrate;
+    ::android::base::unique_fd mFd;
+};
+
+}  // namespace aidl::android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/CanBusVirtual.cpp b/automotive/can/aidl/default/CanBusVirtual.cpp
new file mode 100644
index 0000000..28a1258
--- /dev/null
+++ b/automotive/can/aidl/default/CanBusVirtual.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CanBusVirtual.h"
+
+#include <android-base/logging.h>
+#include <libnetdevice/libnetdevice.h>
+
+namespace aidl::android::hardware::automotive::can {
+
+using namespace ::android;
+
+CanBusVirtual::CanBusVirtual(const std::string& ifname) : CanBus(ifname) {}
+
+Result CanBusVirtual::preUp() {
+    if (netdevice::exists(mIfname)) return Result::OK;
+
+    LOG(DEBUG) << "Virtual interface " << mIfname << " doesn't exist, creating...";
+    mWasCreated = true;
+    if (!netdevice::add(mIfname, "vcan")) {
+        LOG(ERROR) << "Can't create vcan interface " << mIfname;
+        return Result::UNKNOWN_ERROR;
+    }
+
+    return Result::OK;
+}
+
+bool CanBusVirtual::postDown() {
+    if (mWasCreated) {
+        mWasCreated = false;
+        if (!netdevice::del(mIfname)) {
+            LOG(ERROR) << "Couldn't remove vcan interface " << mIfname;
+            return false;
+        }
+    }
+    return true;
+}
+
+}  // namespace aidl::android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/CanBusVirtual.h b/automotive/can/aidl/default/CanBusVirtual.h
new file mode 100644
index 0000000..9c5d35d
--- /dev/null
+++ b/automotive/can/aidl/default/CanBusVirtual.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "CanBus.h"
+
+namespace aidl::android::hardware::automotive::can {
+
+class CanBusVirtual : public CanBus {
+  public:
+    CanBusVirtual(const std::string& ifname);
+
+  protected:
+    virtual Result preUp() override;
+    virtual bool postDown() override;
+
+  private:
+    bool mWasCreated = false;
+};
+
+}  // namespace aidl::android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/CanController.cpp b/automotive/can/aidl/default/CanController.cpp
new file mode 100644
index 0000000..e4b5306
--- /dev/null
+++ b/automotive/can/aidl/default/CanController.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CanController.h"
+
+#include "CanBusNative.h"
+#include "CanBusSlcan.h"
+#include "CanBusVirtual.h"
+
+#include <android-base/format.h>
+#include <android-base/logging.h>
+
+#include <automotive/filesystem>
+#include <fstream>
+#include <regex>
+
+namespace aidl::android::hardware::automotive::can {
+
+namespace fs = ::android::hardware::automotive::filesystem;
+
+namespace fsErrors {
+static const std::error_code ok;
+static const std::error_code eperm(EPERM, std::generic_category());
+static const std::error_code enoent(ENOENT, std::generic_category());
+static const std::error_code eacces(EACCES, std::generic_category());
+}  // namespace fsErrors
+
+/* In the /sys/devices tree, there are files called "serial", which contain the serial numbers
+ * for various devices. The exact location inside of this directory is dependent upon the
+ * hardware we are running on, so we have to start from /sys/devices and work our way down. */
+static const fs::path kDevPath("/sys/devices/");
+static const std::regex kTtyRe("^tty[A-Z]+[0-9]+$");
+static constexpr auto kOpts = ~(fs::directory_options::follow_directory_symlink |
+                                fs::directory_options::skip_permission_denied);
+
+constexpr auto ok = &ndk::ScopedAStatus::ok;
+
+/**
+ * A helper object to associate the interface name and type of a USB to CAN adapter.
+ */
+struct UsbCanIface {
+    InterfaceType iftype;
+    std::string ifaceName;
+};
+
+static bool isValidName(const std::string& name) {
+    static const std::regex nameRE("^[a-zA-Z0-9_]{1,32}$");
+    return std::regex_match(name, nameRE);
+}
+
+/**
+ * Given a path, get the last element from it.
+ *
+ * \param itrPath - the path we want the last element of
+ * \return - the last element in the path (in string form).
+ */
+static std::string getLeaf(const fs::path& itrPath) {
+    /* end() returns an iterator one past the leaf of the path, so we've overshot
+    decrement (--) to go back one to the leaf
+    dereference and now we have our leaf. */
+    return *(--(itrPath.end()));
+}
+
+static ndk::ScopedAStatus resultToStatus(Result res, const std::string& msg = "") {
+    if (msg.empty()) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(static_cast<int>(res)));
+    }
+    return ndk::ScopedAStatus(
+            AStatus_fromServiceSpecificErrorWithMessage(static_cast<int>(res), msg.c_str()));
+}
+
+/**
+ * Given a UsbCanIface object, get the ifaceName given the serialPath.
+ *
+ * \param serialPath - Absolute path to a "serial" file for a given device in /sys.
+ * \return A populated UsbCanIface. On failure, nullopt is returned.
+ */
+static std::optional<UsbCanIface> getIfaceName(const fs::path& serialPath) {
+    std::error_code fsStatus;
+    // Since the path is to a file called "serial", we need to search its parent directory.
+    fs::recursive_directory_iterator fsItr(serialPath.parent_path(), kOpts, fsStatus);
+    if (fsStatus != fsErrors::ok) {
+        LOG(ERROR) << "Failed to open " << serialPath.parent_path();
+        return std::nullopt;
+    }
+
+    for (; fsStatus == fsErrors::ok && fsItr != fs::recursive_directory_iterator();
+         fsItr.increment(fsStatus)) {
+        /* We want either a directory called "net" or a directory that looks like tty<something>, so
+         * skip files. */
+        bool isDir = fsItr->is_directory(fsStatus);
+        if (fsStatus != fsErrors::ok || !isDir) continue;
+
+        std::string currentDir = getLeaf(fsItr->path());
+        if (currentDir == "net") {
+            /* This device is a SocketCAN device. The iface name is the only directory under
+             * net/. Multiple directories under net/ is an error.*/
+            fs::directory_iterator netItr(fsItr->path(), kOpts, fsStatus);
+            if (fsStatus != fsErrors::ok) {
+                LOG(ERROR) << "Failed to open " << fsItr->path() << " to get net name!";
+                return std::nullopt;
+            }
+
+            // The leaf of our path should be the interface name.
+            std::string netName = getLeaf(netItr->path());
+
+            // Check if there is more than one item in net/
+            netItr.increment(fsStatus);
+            if (fsStatus != fsErrors::ok) {
+                // It's possible we have a valid net name, but this is most likely an error.
+                LOG(ERROR) << "Failed to verify " << fsItr->path() << " has valid net name!";
+                return std::nullopt;
+            }
+            if (netItr != fs::directory_iterator()) {
+                // There should never be more than one name under net/
+                LOG(ERROR) << "Found more than one net name in " << fsItr->path() << "!";
+                return std::nullopt;
+            }
+            return {{InterfaceType::NATIVE, netName}};
+        } else if (std::regex_match(currentDir, kTtyRe)) {
+            // This device is a USB serial device, and currentDir is the tty name.
+            return {{InterfaceType::SLCAN, "/dev/" + currentDir}};
+        }
+    }
+
+    // check if the loop above exited due to a c++fs error.
+    if (fsStatus != fsErrors::ok) {
+        LOG(ERROR) << "Failed search filesystem: " << fsStatus;
+    }
+    return std::nullopt;
+}
+
+/**
+ * A helper function to read the serial number from a "serial" file in /sys/devices/
+ *
+ * \param serialnoPath - path to the file to read.
+ * \return the serial number, or nullopt on failure.
+ */
+static std::optional<std::string> readSerialNo(const std::string& serialnoPath) {
+    std::ifstream serialnoStream(serialnoPath);
+    std::string serialno;
+    if (!serialnoStream.good()) {
+        LOG(ERROR) << "Failed to read serial number from " << serialnoPath;
+        return std::nullopt;
+    }
+    std::getline(serialnoStream, serialno);
+    return serialno;
+}
+
+/**
+ * Searches for USB devices found in /sys/devices/, and attempts to find a device matching the
+ * provided list of serial numbers.
+ *
+ * \param configSerialnos - a list of serial number (suffixes) from the HAL config.
+ * \param iftype - the type of the interface to be located.
+ * \return a matching USB device. On failure, std::nullopt is returned.
+ */
+static std::optional<UsbCanIface> findUsbDevice(const std::vector<std::string>& configSerialnos) {
+    std::error_code fsStatus;
+    fs::recursive_directory_iterator fsItr(kDevPath, kOpts, fsStatus);
+    if (fsStatus != fsErrors::ok) {
+        LOG(ERROR) << "Failed to open " << kDevPath;
+        return std::nullopt;
+    }
+
+    for (; fsStatus == fsErrors::ok && fsItr != fs::recursive_directory_iterator();
+         fsItr.increment(fsStatus)) {
+        // We want to find a file called "serial", which is in a directory somewhere. Skip files.
+        bool isDir = fsItr->is_directory(fsStatus);
+        if (fsStatus != fsErrors::ok) {
+            LOG(ERROR) << "Failed check if " << fsStatus;
+            return std::nullopt;
+        }
+        if (!isDir) continue;
+
+        auto serialnoPath = fsItr->path() / "serial";
+        bool isReg = fs::is_regular_file(serialnoPath, fsStatus);
+
+        /* Make sure we have permissions to this directory, ignore enoent, since the file
+         * "serial" may not exist, which is ok. */
+        if (fsStatus == fsErrors::eperm || fsStatus == fsErrors::eacces) {
+            /* This means we  don't have access to this directory. If we recurse into it, this
+             * will cause the iterator to loose its state and we'll crash. */
+            fsItr.disable_recursion_pending();
+            continue;
+        }
+        if (fsStatus == fsErrors::enoent) continue;
+        if (fsStatus != fsErrors::ok) {
+            LOG(WARNING) << "An unexpected error occurred while checking for serialno: "
+                         << fsStatus;
+            continue;
+        }
+        if (!isReg) continue;
+
+        // we found a serial number
+        auto serialno = readSerialNo(serialnoPath);
+        if (!serialno.has_value()) continue;
+
+        // see if the serial number exists in the config
+        for (auto&& cfgSn : configSerialnos) {
+            if (serialno->ends_with(std::string(cfgSn))) {
+                auto ifaceInfo = getIfaceName(serialnoPath);
+                if (!ifaceInfo.has_value()) break;
+                return ifaceInfo;
+            }
+        }
+    }
+    if (fsStatus != fsErrors::ok) {
+        LOG(ERROR) << "Error searching filesystem: " << fsStatus;
+        return std::nullopt;
+    }
+    return std::nullopt;
+}
+
+ndk::ScopedAStatus CanController::getSupportedInterfaceTypes(
+        std::vector<InterfaceType>* supportedTypes) {
+    *supportedTypes = {InterfaceType::VIRTUAL, InterfaceType::NATIVE, InterfaceType::SLCAN};
+    return ok();
+}
+
+ndk::ScopedAStatus CanController::getInterfaceName(const std::string& busName,
+                                                   std::string* ifaceName) {
+    *ifaceName = {};
+    if (mBusesByName.find(busName) == mBusesByName.end()) {
+        return resultToStatus(Result::BAD_BUS_NAME, fmt::format("{} doesn't exist", busName));
+    }
+    *ifaceName = std::string(mBusesByName[busName]->getIfaceName());
+    return ok();
+}
+
+ndk::ScopedAStatus CanController::upBus(const BusConfig& config, std::string* ifaceName) {
+    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));
+    } 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));
+    }
+
+    if (config.interfaceId.getTag() == BusConfig::InterfaceId::Tag::virtualif) {
+        auto& virtualif = config.interfaceId.get<BusConfig::InterfaceId::Tag::virtualif>();
+        mBusesByName[config.name] = std::make_unique<CanBusVirtual>(virtualif.ifname);
+    }
+
+    else if (config.interfaceId.getTag() == BusConfig::InterfaceId::Tag::nativeif) {
+        auto& nativeif = config.interfaceId.get<BusConfig::InterfaceId::Tag::nativeif>();
+        std::string ifaceName;
+        if (nativeif.interfaceId.getTag() == NativeInterface::InterfaceId::Tag::serialno) {
+            // Configure by serial number.
+            auto selectedDevice = findUsbDevice(
+                    nativeif.interfaceId.get<NativeInterface::InterfaceId::Tag::serialno>());
+            // verify the returned device is the correct one
+            if (!selectedDevice.has_value() || selectedDevice->iftype != InterfaceType::NATIVE) {
+                return resultToStatus(
+                        Result::BAD_INTERFACE_ID,
+                        "Couldn't find a native socketcan device with the given serial number(s)");
+            }
+            ifaceName = selectedDevice->ifaceName;
+        } else {
+            // configure by iface name.
+            ifaceName = nativeif.interfaceId.get<NativeInterface::InterfaceId::Tag::ifname>();
+        }
+        mBusesByName[config.name] = std::make_unique<CanBusNative>(ifaceName, config.bitrate);
+    }
+
+    else if (config.interfaceId.getTag() == BusConfig::InterfaceId::Tag::slcan) {
+        auto& slcanif = config.interfaceId.get<BusConfig::InterfaceId::Tag::slcan>();
+        std::string ttyName;
+        if (slcanif.interfaceId.getTag() == SlcanInterface::InterfaceId::Tag::serialno) {
+            // Configure by serial number.
+            auto selectedDevice = findUsbDevice(
+                    slcanif.interfaceId.get<SlcanInterface::InterfaceId::Tag::serialno>());
+            if (!selectedDevice.has_value() || selectedDevice->iftype != InterfaceType::SLCAN) {
+                return resultToStatus(
+                        Result::BAD_INTERFACE_ID,
+                        "Couldn't find a slcan device with the given serial number(s)");
+            }
+            ttyName = selectedDevice->ifaceName;
+        } else {
+            // Configure by tty name.
+            ttyName = slcanif.interfaceId.get<SlcanInterface::InterfaceId::Tag::ttyname>();
+        }
+        mBusesByName[config.name] = std::make_unique<CanBusSlcan>(ttyName, config.bitrate);
+    }
+
+    else if (config.interfaceId.getTag() == BusConfig::InterfaceId::Tag::indexed) {
+        return resultToStatus(Result::NOT_SUPPORTED,
+                              "Indexed devices are not supported in this implementation");
+    } else {
+        // this shouldn't happen.
+        return resultToStatus(Result::UNKNOWN_ERROR, "Unknown interface id type");
+    }
+
+    Result result = mBusesByName[config.name]->up();
+    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));
+    }
+
+    *ifaceName = mBusesByName[config.name]->getIfaceName();
+    return ok();
+}
+
+ndk::ScopedAStatus CanController::downBus(const std::string& busName) {
+    if (mBusesByName.find(busName) == mBusesByName.end()) {
+        return resultToStatus(
+                Result::UNKNOWN_ERROR,
+                fmt::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));
+    }
+    mBusesByName.erase(busName);
+    return ok();
+}
+}  // namespace aidl::android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/CanController.h b/automotive/can/aidl/default/CanController.h
new file mode 100644
index 0000000..784906e
--- /dev/null
+++ b/automotive/can/aidl/default/CanController.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/automotive/can/BnCanController.h>
+
+#include "CanBus.h"
+
+#include <aidl/android/hardware/automotive/can/Result.h>
+
+#include <map>
+#include <string>
+
+namespace aidl::android::hardware::automotive::can {
+
+class CanController : public BnCanController {
+  public:
+    ndk::ScopedAStatus getSupportedInterfaceTypes(
+            std::vector<InterfaceType>* supportedTypes) override;
+
+    ndk::ScopedAStatus getInterfaceName(const std::string& busName,
+                                        std::string* ifaceName) override;
+
+    ndk::ScopedAStatus upBus(const BusConfig& config, std::string* ifaceName) override;
+
+    ndk::ScopedAStatus downBus(const std::string& busName) override;
+
+  private:
+    std::map<std::string, std::unique_ptr<CanBus>> mBusesByName = {};
+};
+}  // namespace aidl::android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/android.hardware.automotive.can.rc b/automotive/can/aidl/default/android.hardware.automotive.can.rc
new file mode 100644
index 0000000..f843752
--- /dev/null
+++ b/automotive/can/aidl/default/android.hardware.automotive.can.rc
@@ -0,0 +1,5 @@
+service android.hardware.automotive.can /vendor/bin/hw/android.hardware.automotive.can-service
+    class hal
+    capabilities NET_ADMIN
+    user vehicle_network
+    group system inet
diff --git a/automotive/can/aidl/default/android.hardware.automotive.can.xml b/automotive/can/aidl/default/android.hardware.automotive.can.xml
new file mode 100644
index 0000000..873f333
--- /dev/null
+++ b/automotive/can/aidl/default/android.hardware.automotive.can.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.automotive.can</name>
+        <version>1</version>
+        <interface>
+            <name>ICanController</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/automotive/can/aidl/default/service.cpp b/automotive/can/aidl/default/service.cpp
new file mode 100644
index 0000000..eb45167
--- /dev/null
+++ b/automotive/can/aidl/default/service.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CanController.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+namespace android::hardware::automotive::can {
+
+using namespace std::string_literals;
+using ::aidl::android::hardware::automotive::can::CanController;
+
+extern "C" int main() {
+    base::SetDefaultTag("CanController");
+    base::SetMinimumLogSeverity(base::VERBOSE);
+
+    LOG(VERBOSE) << "Starting up...";
+    auto service = ndk::SharedRefBase::make<CanController>();
+    const auto instance = CanController::descriptor + "/default"s;
+    const auto status = AServiceManager_addService(service->asBinder().get(), instance.c_str());
+    CHECK_EQ(status, STATUS_OK) << "Failed to add service " << instance;
+    LOG(VERBOSE) << "Started successfully!";
+
+    ABinderProcess_joinThreadPool();
+    LOG(FATAL) << "CanController exited unexpectedly!";
+    return EXIT_FAILURE;
+}
+}  // namespace android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/tools/configurator/Android.bp b/automotive/can/aidl/default/tools/configurator/Android.bp
new file mode 100644
index 0000000..1169894
--- /dev/null
+++ b/automotive/can/aidl/default/tools/configurator/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_binary {
+    name: "canhalconfigurator-aidl",
+    init_rc: ["canhalconfigurator-aidl.rc"],
+    defaults: ["android.hardware.automotive.can@defaults"],
+    srcs: [
+        "canhalconfigurator.cpp",
+        "canprototools.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libprotobuf-cpp-full",
+    ],
+    static_libs: [
+        "android.hardware.automotive.can-V1-ndk",
+        "android.hardware.automotive.can-aidl-config-format",
+    ],
+}
diff --git a/automotive/can/aidl/default/tools/configurator/canhalconfigurator-aidl.rc b/automotive/can/aidl/default/tools/configurator/canhalconfigurator-aidl.rc
new file mode 100644
index 0000000..e1b4d35
--- /dev/null
+++ b/automotive/can/aidl/default/tools/configurator/canhalconfigurator-aidl.rc
@@ -0,0 +1,3 @@
+service canhalconfigurator /system/bin/canhalconfigurator-aidl
+  class core
+  oneshot
diff --git a/automotive/can/aidl/default/tools/configurator/canhalconfigurator.cpp b/automotive/can/aidl/default/tools/configurator/canhalconfigurator.cpp
new file mode 100644
index 0000000..94e77b4
--- /dev/null
+++ b/automotive/can/aidl/default/tools/configurator/canhalconfigurator.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "canbus_config.pb.h"
+#include "canprototools.h"
+
+#include <aidl/android/hardware/automotive/can/ICanController.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include <chrono>
+#include <thread>
+
+namespace android::hardware::automotive::can {
+
+using namespace std::string_literals;
+using ::aidl::android::hardware::automotive::can::ICanController;
+
+static constexpr std::string_view kDefaultConfigPath = "/etc/canbus_config.pb";
+
+/**
+ * Takes output from parsed protobuf config and uses it to configure the CAN HAL.
+ *
+ * \param pb_cfg is an instance of the autogenerated protobuf object for our configuration.
+ * \return boolean status, true on success, false on failure.
+ */
+static bool processPbCfg(const config::CanBusConfig& pb_cfg) {
+    for (auto const& bus : pb_cfg.buses()) {
+        if (bus.name().empty()) {
+            LOG(ERROR) << "Invalid config: Bus config must have a valid name field";
+            return false;
+        }
+
+        auto busCfgMaybe = config::fromPbBus(bus);
+        if (!busCfgMaybe.has_value()) {
+            return false;
+        }
+        auto busCfg = *busCfgMaybe;
+
+        const auto instance = ICanController::descriptor + "/default"s;
+        const auto service = ICanController::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(instance.c_str())));
+        if (service == nullptr) {
+            LOG(FATAL) << "Can't find CAN HAL! (has it started yet?)";
+            return false;
+        }
+
+        LOG(VERBOSE) << "Bringing up a " << busCfg.name << " @ " << busCfg.bitrate;
+
+        std::string ifaceName;
+        const auto status = service->upBus(busCfg, &ifaceName);
+        if (!status.isOk() && status.getExceptionCode() != EX_SERVICE_SPECIFIC) {
+            LOG(FATAL) << "Binder transaction failed!" << status.getStatus();
+            return false;
+        } else if (!status.isOk()) {
+            LOG(ERROR) << "upBus failed: " << config::resultStringFromStatus(status) << ": "
+                       << status.getMessage();
+            continue;
+        }
+
+        LOG(INFO) << bus.name() << " has been successfully configured on " << ifaceName;
+    }
+    return true;
+}
+
+/**
+ * This kicks off the CAN HAL configuration process. This starts the following:
+ *     1. Reading the config file
+ *     2. Setting up CAN buses
+ *     3. Handling services
+ * \param filepath is a string specifying the absolute path of the config file
+ * \return boolean status, true on success, false on failure
+ */
+static bool configuratorStart(const std::string& filepath) {
+    base::SetDefaultTag("CanConfigurator");
+    auto pbCfg = config::parseConfigFile(filepath);
+    if (!pbCfg.has_value()) {
+        return false;
+    }
+    // process the rest of the config file data and configure the CAN buses.
+    if (!processPbCfg(*pbCfg)) {
+        return false;
+    }
+    LOG(INFO) << "CAN HAL has been configured!";
+    return true;
+}
+
+extern "C" int main(int argc, char* argv[]) {
+    std::string configFilepath = static_cast<std::string>(kDefaultConfigPath);
+
+    // allow for CLI specification of a config file.
+    if (argc == 2) {
+        configFilepath = argv[1];
+    } else if (argc > 2) {
+        std::cerr << "usage: " << argv[0] << " [optional config filepath]";
+        return 1;
+    }
+
+    if (!configuratorStart(configFilepath)) {
+        return 1;
+    }
+    return 0;
+}
+
+}  // namespace android::hardware::automotive::can
diff --git a/automotive/can/aidl/default/tools/configurator/canprototools.cpp b/automotive/can/aidl/default/tools/configurator/canprototools.cpp
new file mode 100644
index 0000000..2aea315
--- /dev/null
+++ b/automotive/can/aidl/default/tools/configurator/canprototools.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "canprototools.h"
+
+#include <aidl/android/hardware/automotive/can/IndexedInterface.h>
+#include <aidl/android/hardware/automotive/can/NativeInterface.h>
+#include <aidl/android/hardware/automotive/can/SlcanInterface.h>
+#include <aidl/android/hardware/automotive/can/VirtualInterface.h>
+
+#include <android-base/logging.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/text_format.h>
+
+#include <fstream>
+
+namespace android::hardware::automotive::can::config {
+
+using ::aidl::android::hardware::automotive::can::BusConfig;
+using ::aidl::android::hardware::automotive::can::IndexedInterface;
+using ::aidl::android::hardware::automotive::can::InterfaceType;
+using ::aidl::android::hardware::automotive::can::NativeInterface;
+using ::aidl::android::hardware::automotive::can::Result;
+using ::aidl::android::hardware::automotive::can::SlcanInterface;
+using ::aidl::android::hardware::automotive::can::VirtualInterface;
+
+/**
+ * Helper function for parseConfigFile. readString is used to get the fist n characters (n) from an
+ * istream object (s) and return it as a string object.
+ *
+ * \param s istream of the file you intend to read.
+ * \param n streamsize object of the number of characters you'd like.
+ * \return optional string containing up to n characters from the stream(s) you provided.
+ */
+static std::optional<std::string> readString(std::istream& s, std::streamsize n) {
+    char buff[n];
+    auto got = s.read(buff, n).gcount();
+    if (!s.good() && !s.eof()) return std::nullopt;
+    return std::string(buff, 0, std::min(n, got));
+}
+
+std::optional<CanBusConfig> parseConfigFile(const std::string& filepath) {
+    std::ifstream cfg_stream(filepath);
+
+    // text headers that would be present in a plaintext proto config file.
+    static const std::array<std::string, 3> text_headers = {"buses", "#", "controller"};
+    auto cfg_file_snippet = readString(cfg_stream, 10);
+
+    if (!cfg_file_snippet.has_value()) {
+        LOG(ERROR) << "Can't open " << filepath << " for reading";
+        return std::nullopt;
+    }
+    cfg_stream.seekg(0);
+
+    // check if any of the textHeaders are at the start of the config file.
+    bool text_format = false;
+    for (auto const& header : text_headers) {
+        if (cfg_file_snippet->compare(0, header.length(), header) == 0) {
+            text_format = true;
+            break;
+        }
+    }
+
+    CanBusConfig config;
+    if (text_format) {
+        google::protobuf::io::IstreamInputStream pb_stream(&cfg_stream);
+        if (!google::protobuf::TextFormat::Parse(&pb_stream, &config)) {
+            LOG(ERROR) << "Failed to parse (text format) " << filepath;
+            return std::nullopt;
+        }
+    } else if (!config.ParseFromIstream(&cfg_stream)) {
+        LOG(ERROR) << "Failed to parse (binary format) " << filepath;
+        return std::nullopt;
+    }
+    return config;
+}
+
+std::optional<BusConfig> fromPbBus(const Bus& pb_bus) {
+    BusConfig bus_cfg = {};
+    bus_cfg.name = pb_bus.name();
+
+    switch (pb_bus.iface_type_case()) {
+        case Bus::kNative: {
+            const std::string ifname = pb_bus.native().ifname();
+            const std::vector<std::string> serials = {pb_bus.native().serialno().begin(),
+                                                      pb_bus.native().serialno().end()};
+            if (ifname.empty() == serials.empty()) {
+                LOG(ERROR) << "Invalid config: native type bus must have an iface name xor a "
+                           << "serial number";
+                return std::nullopt;
+            }
+            bus_cfg.bitrate = pb_bus.bitrate();
+            NativeInterface nativeif = {};
+            if (!ifname.empty())
+                nativeif.interfaceId.set<NativeInterface::InterfaceId::Tag::ifname>(ifname);
+            if (!serials.empty())
+                nativeif.interfaceId.set<NativeInterface::InterfaceId::Tag::serialno>(serials);
+            bus_cfg.interfaceId.set<BusConfig::InterfaceId::Tag::nativeif>(nativeif);
+            break;
+        }
+        case Bus::kSlcan: {
+            const std::string ttyname = pb_bus.slcan().ttyname();
+            const std::vector<std::string> serials = {pb_bus.slcan().serialno().begin(),
+                                                      pb_bus.slcan().serialno().end()};
+            if (ttyname.empty() == serials.empty()) {
+                LOG(ERROR) << "Invalid config: slcan type bus must have a tty name xor a serial "
+                           << "number";
+                return std::nullopt;
+            }
+            bus_cfg.bitrate = pb_bus.bitrate();
+            SlcanInterface slcan = {};
+            if (!ttyname.empty())
+                slcan.interfaceId.set<SlcanInterface::InterfaceId::Tag::ttyname>(ttyname);
+            if (!serials.empty())
+                slcan.interfaceId.set<SlcanInterface::InterfaceId::Tag::serialno>(serials);
+            bus_cfg.interfaceId.set<BusConfig::InterfaceId::Tag::slcan>(slcan);
+            break;
+        }
+        case Bus::kVirtual: {
+            // Theoretically, we could just create the next available vcan iface.
+            const std::string ifname = pb_bus.virtual_().ifname();
+            if (ifname.empty()) {
+                LOG(ERROR) << "Invalid config: native type bus must have an iface name";
+                return std::nullopt;
+            }
+            VirtualInterface virtualif = {};
+            virtualif.ifname = ifname;
+            bus_cfg.interfaceId.set<BusConfig::InterfaceId::Tag::virtualif>(virtualif);
+            break;
+        }
+        case Bus::kIndexed: {
+            const uint8_t index = pb_bus.indexed().index();
+            if (index > UINT8_MAX) {
+                LOG(ERROR) << "Interface index out of range: " << index;
+                return std::nullopt;
+            }
+            IndexedInterface indexedif = {};
+            indexedif.index = index;
+            bus_cfg.interfaceId.set<BusConfig::InterfaceId::Tag::indexed>(indexedif);
+            break;
+        }
+        default:
+            LOG(ERROR) << "Invalid config: bad interface type for " << bus_cfg.name;
+            return std::nullopt;
+    }
+    return bus_cfg;
+}
+
+std::optional<InterfaceType> getHalIftype(const Bus& pb_bus) {
+    switch (pb_bus.iface_type_case()) {
+        case Bus::kNative:
+            return InterfaceType::NATIVE;
+        case Bus::kSlcan:
+            return InterfaceType::SLCAN;
+        case Bus::kVirtual:
+            return InterfaceType::VIRTUAL;
+        case Bus::kIndexed:
+            return InterfaceType::INDEXED;
+        default:
+            return std::nullopt;
+    }
+}
+
+std::string resultStringFromStatus(const ndk::ScopedAStatus& status) {
+    const auto res = static_cast<Result>(status.getServiceSpecificError());
+    switch (res) {
+        case Result::OK:
+            return "OK";
+        case Result::UNKNOWN_ERROR:
+            return "UNKNOWN_ERROR";
+        case Result::INVALID_STATE:
+            return "INVALID_STATE";
+        case Result::NOT_SUPPORTED:
+            return "NOT_SUPPORTED";
+        case Result::BAD_INTERFACE_ID:
+            return "BAD_INTERFACE_ID";
+        case Result::BAD_BITRATE:
+            return "BAD_BITRATE";
+        case Result::BAD_BUS_NAME:
+            return "BAD_BUS_NAME";
+        case Result::INTERFACE_DOWN:
+            return "INTERFACE_DOWN";
+        default:
+            return "Invalid Result!";
+    }
+}
+
+}  // namespace android::hardware::automotive::can::config
diff --git a/automotive/can/aidl/default/tools/configurator/canprototools.h b/automotive/can/aidl/default/tools/configurator/canprototools.h
new file mode 100644
index 0000000..377ee7f
--- /dev/null
+++ b/automotive/can/aidl/default/tools/configurator/canprototools.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "canbus_config.pb.h"
+
+#include <aidl/android/hardware/automotive/can/BusConfig.h>
+#include <aidl/android/hardware/automotive/can/InterfaceType.h>
+#include <aidl/android/hardware/automotive/can/Result.h>
+
+namespace android::hardware::automotive::can::config {
+
+/**
+ * This reads the protobuf config file into a protobuf object. Both text based protobuf files as
+ * well as binary format protobuf files are supported.
+ *
+ * \param filepath string containing the name of the config file to read.
+ * \return a CanBusConfig protobuf object constructed from the config file.
+ */
+std::optional<CanBusConfig> parseConfigFile(const std::string& filepath);
+
+/**
+ * Converts protobuf format single-bus config object to a HAL bus config object.
+ *
+ * \param pb_bus is the protobuf object representing a the configuration of one CAN bus.
+ * \return a converted HAL bus config object.
+ */
+std::optional<::aidl::android::hardware::automotive::can::BusConfig> fromPbBus(const Bus& pb_bus);
+
+/**
+ * Get the CAN HAL interface type specified by a given protobuf config object.
+ *
+ * \param pb_bus is the protobuf object representing a the configuration of one CAN bus.
+ * \return the CAN HAL interface type.
+ */
+std::optional<::aidl::android::hardware::automotive::can::InterfaceType> getHalIftype(
+        const Bus& pb_bus);
+
+std::string resultStringFromStatus(const ndk::ScopedAStatus& status);
+
+}  // namespace android::hardware::automotive::can::config
diff --git a/automotive/can/aidl/default/tools/configurator/proto/Android.bp b/automotive/can/aidl/default/tools/configurator/proto/Android.bp
new file mode 100644
index 0000000..da1b37c
--- /dev/null
+++ b/automotive/can/aidl/default/tools/configurator/proto/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_static {
+    name: "android.hardware.automotive.can-aidl-config-format",
+    defaults: ["android.hardware.automotive.can@defaults"],
+    proto: {
+        export_proto_headers: true,
+        type: "full",
+    },
+    strip: {
+        keep_symbols: true,
+    },
+    srcs: ["canbus_config.proto"],
+}
diff --git a/automotive/can/aidl/default/tools/configurator/proto/canbus_config.proto b/automotive/can/aidl/default/tools/configurator/proto/canbus_config.proto
new file mode 100644
index 0000000..b03b035
--- /dev/null
+++ b/automotive/can/aidl/default/tools/configurator/proto/canbus_config.proto
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.can.config;
+
+message IfaceNative {
+    string ifname = 1;
+    repeated string serialno = 2;
+};
+
+message IfaceSlcan {
+    string ttyname = 1;
+    repeated string serialno = 2;
+};
+
+message IfaceVirtual {
+    string ifname = 1;
+};
+
+message IfaceIndexed {
+    uint32 index = 1;
+};
+
+message Bus {
+    string name = 1;  // this is the name presented in the HAL
+    oneof iface_type {
+        IfaceNative native = 2;
+        IfaceSlcan slcan = 3;
+        IfaceVirtual virtual = 4;
+        IfaceIndexed indexed = 5;
+    }
+    uint32 bitrate = 6;
+};
+
+message CanBusConfig {
+    repeated Bus buses = 1;
+};
diff --git a/automotive/can/aidl/vts/functional/Android.bp b/automotive/can/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..b816a49
--- /dev/null
+++ b/automotive/can/aidl/vts/functional/Android.bp
@@ -0,0 +1,51 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsHalCanControllerV1_0Test",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "android.hardware.automotive.can@defaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    cpp_std: "experimental",
+    srcs: [
+        "CanControllerAidlTest.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.automotive.can-V1-ndk",
+        "android.hardware.automotive.can@libnetdevice",
+        "libnl++",
+        "libgmock",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/automotive/can/aidl/vts/functional/CanControllerAidlTest.cpp b/automotive/can/aidl/vts/functional/CanControllerAidlTest.cpp
new file mode 100644
index 0000000..c2b2879
--- /dev/null
+++ b/automotive/can/aidl/vts/functional/CanControllerAidlTest.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/automotive/can/BusConfig.h>
+#include <aidl/android/hardware/automotive/can/ICanController.h>
+#include <aidl/android/hardware/automotive/can/Result.h>
+#include <aidl/android/hardware/automotive/can/VirtualInterface.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <gtest/gtest.h>
+#include <libnetdevice/libnetdevice.h>
+#include <libnl++/MessageFactory.h>
+#include <libnl++/Socket.h>
+#include <libnl++/printer.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <chrono>
+#include <thread>
+
+using aidl::android::hardware::automotive::can::BusConfig;
+using aidl::android::hardware::automotive::can::ICanController;
+using aidl::android::hardware::automotive::can::VirtualInterface;
+using namespace std::chrono_literals;
+using namespace std::string_literals;
+
+class CanControllerAidlTest : public ::testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        android::base::SetDefaultTag("CAN_HAL_VTS");
+        android::base::SetMinimumLogSeverity(android::base::VERBOSE);
+        const auto instance = ICanController::descriptor + "/default"s;
+        mCanControllerService = ICanController::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(instance.c_str())));
+
+        ASSERT_NE(mCanControllerService, nullptr);
+    }
+    virtual void TearDown() override {}
+
+    static bool mTestCaseInitialized;
+    std::shared_ptr<ICanController> mCanControllerService;
+};
+
+// we can't test a real bus, since we can't make any assumptions about hardware
+// this checks upBus, getInterfaceName, and downBus
+TEST_P(CanControllerAidlTest, ToggleBus) {
+    const std::string_view canIface = "vcan50";
+    const std::string busName = "VTS_CAN";
+
+    std::string upBusReturn;  // should be vcan50
+    BusConfig config = {};
+    VirtualInterface iface = {};
+    iface.ifname = canIface;
+    config.interfaceId.set<BusConfig::InterfaceId::Tag::virtualif>(iface);
+    config.name = busName;
+    auto aidlStatus = mCanControllerService->upBus(config, &upBusReturn);
+    ASSERT_TRUE(aidlStatus.isOk());
+    EXPECT_EQ(upBusReturn, canIface);
+
+    std::string ifaceName;
+    aidlStatus = mCanControllerService->getInterfaceName(busName, &ifaceName);
+    ASSERT_TRUE(aidlStatus.isOk());
+    EXPECT_EQ(ifaceName, canIface);
+
+    aidlStatus = mCanControllerService->downBus(busName);
+    ASSERT_TRUE(aidlStatus.isOk());
+}
+
+TEST_P(CanControllerAidlTest, GetSupported) {
+    LOG(VERBOSE) << "Get the supported iface types";
+    std::vector<::aidl::android::hardware::automotive::can::InterfaceType> supportedTypes;
+    auto aidlStatus = mCanControllerService->getSupportedInterfaceTypes(&supportedTypes);
+    ASSERT_TRUE(aidlStatus.isOk());
+    EXPECT_FALSE(supportedTypes.empty());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CanControllerAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, CanControllerAidlTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(ICanController::descriptor)),
+        android::PrintInstanceNameToString);
diff --git a/automotive/can/aidl/vts/functional/OWNERS b/automotive/can/aidl/vts/functional/OWNERS
new file mode 100644
index 0000000..85257a3
--- /dev/null
+++ b/automotive/can/aidl/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 533426
+twasilczyk@google.com
+chrisweir@google.com
diff --git a/automotive/vehicle/aidl/Android.bp b/automotive/vehicle/aidl/Android.bp
index 9aeb4d2..18a5046 100644
--- a/automotive/vehicle/aidl/Android.bp
+++ b/automotive/vehicle/aidl/Android.bp
@@ -27,6 +27,7 @@
     srcs: [
         "android/hardware/automotive/vehicle/**/*.aidl",
     ],
+    frozen: false,
     stability: "vintf",
     backend: {
         cpp: {
diff --git a/biometrics/common/aidl/Android.bp b/biometrics/common/aidl/Android.bp
index 3cd76fd..88edf04 100644
--- a/biometrics/common/aidl/Android.bp
+++ b/biometrics/common/aidl/Android.bp
@@ -13,6 +13,7 @@
     srcs: [
         "android/hardware/biometrics/common/*.aidl",
     ],
+    frozen: false,
     stability: "vintf",
     backend: {
         java: {
diff --git a/camera/common/aidl/Android.bp b/camera/common/aidl/Android.bp
index e1c9cc5..4ffcfd9 100644
--- a/camera/common/aidl/Android.bp
+++ b/camera/common/aidl/Android.bp
@@ -11,6 +11,7 @@
     name: "android.hardware.camera.common",
     vendor_available: true,
     srcs: ["android/hardware/camera/common/*.aidl"],
+    frozen: true,
     stability: "vintf",
     backend: {
         cpp: {
diff --git a/camera/device/aidl/Android.bp b/camera/device/aidl/Android.bp
index 2e5b667..bf5bf63 100644
--- a/camera/device/aidl/Android.bp
+++ b/camera/device/aidl/Android.bp
@@ -11,6 +11,7 @@
     name: "android.hardware.camera.device",
     vendor_available: true,
     srcs: ["android/hardware/camera/device/*.aidl"],
+    frozen: false,
     stability: "vintf",
     imports: [
         "android.hardware.common-V2",
diff --git a/camera/metadata/aidl/Android.bp b/camera/metadata/aidl/Android.bp
index 0113a4b..7bec61d 100644
--- a/camera/metadata/aidl/Android.bp
+++ b/camera/metadata/aidl/Android.bp
@@ -11,6 +11,7 @@
     name: "android.hardware.camera.metadata",
     vendor_available: true,
     srcs: ["android/hardware/camera/metadata/*.aidl"],
+    frozen: false,
     stability: "vintf",
     backend: {
         cpp: {
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 9f43219..d4b1fad 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -31,6 +31,13 @@
         <interface>
             <name>IModule</name>
             <instance>default</instance>
+            <instance>a2dp</instance>
+            <instance>bluetooth</instance>
+            <instance>hearing_aid</instance>
+            <instance>msd</instance>
+            <instance>r_submix</instance>
+            <instance>stub</instance>
+            <instance>usb</instance>
         </interface>
         <interface>
             <name>IConfig</name>
@@ -68,6 +75,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.automotive.can</name>
+        <version>1</version>
+        <interface>
+            <name>ICanController</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.automotive.can</name>
         <version>1.0</version>
@@ -577,6 +592,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.sensors</name>
+        <version>2</version>
         <interface>
             <name>ISensors</name>
             <instance>default</instance>
@@ -707,14 +723,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.wifi</name>
-        <version>1.3-6</version>
-        <interface>
-            <name>IWifi</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.uwb</name>
         <version>1</version>
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index b706596..a6dfcaf 100644
--- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -126,15 +126,23 @@
     ASSERT_EQ(Error::NONE, error) << "failed to setReadbackBuffer";
 }
 
-void ComposerClient::getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
-                                                 Dataspace* outDataspace) {
+void ComposerClient::getRequiredReadbackBufferAttributes(Display display,
+                                                         PixelFormat* outPixelFormat,
+                                                         Dataspace* outDataspace) {
+    ASSERT_EQ(Error::NONE, getReadbackBufferAttributes(display, outPixelFormat, outDataspace));
+}
+
+Error ComposerClient::getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
+                                                  Dataspace* outDataspace) {
+    Error error;
     mClient->getReadbackBufferAttributes(
-        display,
-        [&](const auto& tmpError, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) {
-            ASSERT_EQ(Error::NONE, tmpError) << "failed to get readback buffer attributes";
-            *outPixelFormat = tmpOutPixelFormat;
-            *outDataspace = tmpOutDataspace;
-        });
+            display, [&](const Error& tmpError, const PixelFormat& tmpPixelFormat,
+                         const Dataspace& tmpDataspace) {
+                error = tmpError;
+                *outPixelFormat = tmpPixelFormat;
+                *outDataspace = tmpDataspace;
+            });
+    return error;
 }
 
 void ComposerClient::getReadbackBufferFence(Display display, int32_t* outFence) {
diff --git a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
index a1794af..5dd68df 100644
--- a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
@@ -19,6 +19,8 @@
 #include "renderengine/ExternalTexture.h"
 #include "renderengine/impl/ExternalTexture.h"
 
+using ::android::status_t;
+
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -107,6 +109,40 @@
     }
 }
 
+void ReadbackHelper::fillBufferAndGetFence(const sp<GraphicBuffer>& graphicBuffer,
+                                           IComposerClient::Color desiredColor, int* fillFence) {
+    ASSERT_NE(nullptr, fillFence);
+    std::vector<IComposerClient::Color> desiredColors(
+            static_cast<size_t>(graphicBuffer->getWidth() * graphicBuffer->getHeight()));
+    ::android::Rect bounds = graphicBuffer->getBounds();
+    fillColorsArea(desiredColors, static_cast<int32_t>(graphicBuffer->getWidth()),
+                   {bounds.left, bounds.top, bounds.right, bounds.bottom}, desiredColor);
+    ASSERT_NO_FATAL_FAILURE(fillBufferAndGetFence(graphicBuffer, desiredColors, fillFence));
+}
+
+void ReadbackHelper::fillBufferAndGetFence(const sp<GraphicBuffer>& graphicBuffer,
+                                           const std::vector<IComposerClient::Color>& desiredColors,
+                                           int* fillFence) {
+    ASSERT_TRUE(graphicBuffer->getPixelFormat() == ::android::PIXEL_FORMAT_RGB_888 ||
+                graphicBuffer->getPixelFormat() == ::android::PIXEL_FORMAT_RGBA_8888);
+    void* bufData;
+    int32_t bytesPerPixel = -1;
+    int32_t bytesPerStride = -1;
+    status_t status =
+            graphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                &bufData, &bytesPerPixel, &bytesPerStride);
+    ASSERT_EQ(::android::OK, status);
+
+    const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
+                                    ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
+                                    : graphicBuffer->getStride();
+    ReadbackHelper::fillBuffer(graphicBuffer->getWidth(), graphicBuffer->getHeight(), stride,
+                               bufData, static_cast<PixelFormat>(graphicBuffer->getPixelFormat()),
+                               desiredColors);
+    status = graphicBuffer->unlockAsync(fillFence);
+    ASSERT_EQ(::android::OK, status);
+}
+
 void ReadbackHelper::fillBuffer(int32_t width, int32_t height, uint32_t stride, void* bufferData,
                                 PixelFormat pixelFormat,
                                 std::vector<IComposerClient::Color> desiredPixelColors) {
@@ -116,16 +152,16 @@
     for (int row = 0; row < height; row++) {
         for (int col = 0; col < width; col++) {
             int pixel = row * width + col;
-            IComposerClient::Color srcColor = desiredPixelColors[pixel];
+            IComposerClient::Color desiredColor = desiredPixelColors[pixel];
 
             int offset = (row * stride + col) * bytesPerPixel;
             uint8_t* pixelColor = (uint8_t*)bufferData + offset;
-            pixelColor[0] = srcColor.r;
-            pixelColor[1] = srcColor.g;
-            pixelColor[2] = srcColor.b;
+            pixelColor[0] = desiredColor.r;
+            pixelColor[1] = desiredColor.g;
+            pixelColor[2] = desiredColor.b;
 
             if (bytesPerPixel == 4) {
-                pixelColor[3] = srcColor.a;
+                pixelColor[3] = desiredColor.a;
             }
         }
     }
@@ -152,12 +188,14 @@
     }
 }
 
-bool ReadbackHelper::readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace,
-                                       const Error error) {
+bool ReadbackHelper::readbackSupported(PixelFormat pixelFormat, Dataspace dataspace, Error error) {
     if (error != Error::NONE) {
         return false;
     }
-    // TODO: add support for RGBA_1010102
+    return readbackSupported(pixelFormat, dataspace);
+}
+
+bool ReadbackHelper::readbackSupported(PixelFormat pixelFormat, Dataspace dataspace) {
     if (pixelFormat != PixelFormat::RGB_888 && pixelFormat != PixelFormat::RGBA_8888) {
         return false;
     }
@@ -167,71 +205,94 @@
     return true;
 }
 
-void ReadbackHelper::compareColorBuffers(std::vector<IComposerClient::Color>& expectedColors,
-                                         void* bufferData, const uint32_t stride,
-                                         const uint32_t width, const uint32_t height,
-                                         const 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 pixel = row * width + col;
-            int offset = (row * stride + col) * bytesPerPixel;
-            uint8_t* pixelColor = (uint8_t*)bufferData + offset;
+void ReadbackHelper::createReadbackBuffer(uint32_t width, uint32_t height, PixelFormat pixelFormat,
+                                          Dataspace dataspace, sp<GraphicBuffer>* graphicBuffer) {
+    ASSERT_NE(nullptr, graphicBuffer);
+    if (!readbackSupported(pixelFormat, dataspace)) {
+        *graphicBuffer = nullptr;
+    }
+    android::PixelFormat bufferFormat = static_cast<android::PixelFormat>(pixelFormat);
+    uint32_t layerCount = 1;
+    uint64_t usage = static_cast<uint64_t>(static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN) |
+                                           static_cast<uint64_t>(BufferUsage::GPU_TEXTURE));
+    *graphicBuffer = sp<GraphicBuffer>::make(width, height, bufferFormat, layerCount, usage,
+                                             "ReadbackBuffer");
+    ASSERT_NE(nullptr, *graphicBuffer);
+    ASSERT_EQ(::android::OK, (*graphicBuffer)->initCheck());
+}
 
-            ASSERT_EQ(expectedColors[pixel].r, pixelColor[0]);
-            ASSERT_EQ(expectedColors[pixel].g, pixelColor[1]);
-            ASSERT_EQ(expectedColors[pixel].b, pixelColor[2]);
+void ReadbackHelper::compareColorToBuffer(IComposerClient::Color expectedColor,
+                                          const sp<GraphicBuffer>& graphicBuffer, int32_t fence) {
+    std::vector<IComposerClient::Color> expectedColors(
+            static_cast<size_t>(graphicBuffer->getWidth() * graphicBuffer->getHeight()));
+    ::android::Rect bounds = graphicBuffer->getBounds();
+    fillColorsArea(expectedColors, static_cast<int32_t>(graphicBuffer->getWidth()),
+                   {bounds.left, bounds.top, bounds.right, bounds.bottom}, expectedColor);
+    compareColorsToBuffer(expectedColors, graphicBuffer, fence);
+}
+
+void ReadbackHelper::compareColorsToBuffer(std::vector<IComposerClient::Color>& expectedColors,
+                                           const sp<GraphicBuffer>& graphicBuffer, int32_t fence) {
+    ASSERT_TRUE(graphicBuffer->getPixelFormat() == ::android::PIXEL_FORMAT_RGB_888 ||
+                graphicBuffer->getPixelFormat() == ::android::PIXEL_FORMAT_RGBA_8888);
+
+    int bytesPerPixel = -1;
+    int bytesPerStride = -1;
+    void* bufData = nullptr;
+    status_t status = graphicBuffer->lockAsync(GRALLOC_USAGE_SW_READ_OFTEN, &bufData, fence,
+                                               &bytesPerPixel, &bytesPerStride);
+    ASSERT_EQ(::android::OK, status);
+
+    const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
+                                    ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
+                                    : graphicBuffer->getStride();
+
+    if (bytesPerPixel == -1) {
+        PixelFormat pixelFormat = static_cast<PixelFormat>(graphicBuffer->getPixelFormat());
+        bytesPerPixel = ReadbackHelper::GetBytesPerPixel(pixelFormat);
+    }
+    ASSERT_NE(-1, bytesPerPixel);
+    for (int row = 0; row < graphicBuffer->getHeight(); row++) {
+        for (int col = 0; col < graphicBuffer->getWidth(); col++) {
+            int pixel = row * static_cast<int32_t>(graphicBuffer->getWidth()) + col;
+            int offset = (row * static_cast<int32_t>(stride) + col) * bytesPerPixel;
+            uint8_t* pixelColor = (uint8_t*)bufData + offset;
+            const IComposerClient::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]);
         }
     }
+
+    status = graphicBuffer->unlock();
+    ASSERT_EQ(::android::OK, status);
 }
 
 ReadbackBuffer::ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
-                               const std::shared_ptr<Gralloc>& gralloc, uint32_t width,
-                               uint32_t height, PixelFormat pixelFormat, Dataspace dataspace) {
+                               uint32_t width, uint32_t height, PixelFormat pixelFormat) {
     mDisplay = display;
-
     mComposerClient = client;
-    mGralloc = gralloc;
-
-    mPixelFormat = pixelFormat;
-    mDataspace = dataspace;
-
     mWidth = width;
     mHeight = height;
+    mPixelFormat = pixelFormat;
     mLayerCount = 1;
-    mFormat = mPixelFormat;
     mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE);
-
-    mAccessRegion.top = 0;
-    mAccessRegion.left = 0;
-    mAccessRegion.width = width;
-    mAccessRegion.height = height;
 }
 
 void ReadbackBuffer::setReadbackBuffer() {
-    mBufferHandle.reset(new Gralloc::NativeHandleWrapper(
-            mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
-                               /*import*/ true, &mStride)));
-    ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight,
-                                                  mLayerCount, mFormat, mUsage, mStride));
-    ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle->get(), -1));
+    mGraphicBuffer = sp<GraphicBuffer>::make(mWidth, mHeight,
+                                             static_cast<::android::PixelFormat>(mPixelFormat),
+                                             mLayerCount, mUsage, "ReadbackBuffer");
+    ASSERT_NE(nullptr, mGraphicBuffer);
+    ASSERT_EQ(::android::OK, mGraphicBuffer->initCheck());
+    mComposerClient->setReadbackBuffer(mDisplay, mGraphicBuffer->handle, -1 /* fence */);
 }
 
 void ReadbackBuffer::checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors) {
     // lock buffer for reading
     int32_t fenceHandle;
     ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle));
-
-    void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, fenceHandle);
-    ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
-    ReadbackHelper::compareColorBuffers(expectedColors, bufData, mStride, mWidth, mHeight,
-                                        mPixelFormat);
-    int32_t unlockFence = mGralloc->unlock(mBufferHandle->get());
-    if (unlockFence != -1) {
-        sync_wait(unlockFence, -1);
-        close(unlockFence);
-    }
+    ReadbackHelper::compareColorsToBuffer(expectedColors, mGraphicBuffer, fenceHandle);
 }
 
 void TestColorLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
index 1700b2a..254ff3b 100644
--- a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
+++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
@@ -83,9 +83,7 @@
 void TestRenderEngine::checkColorBuffer(std::vector<V2_2::IComposerClient::Color>& expectedColors) {
     void* bufferData;
     ASSERT_EQ(0, mGraphicBuffer->lock(mGraphicBuffer->getUsage(), &bufferData));
-    ReadbackHelper::compareColorBuffers(expectedColors, bufferData, mGraphicBuffer->getStride(),
-                                        mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight(),
-                                        mFormat);
+    ReadbackHelper::compareColorsToBuffer(expectedColors, mGraphicBuffer, -1 /* fence */);
     ASSERT_EQ(0, mGraphicBuffer->unlock());
 }
 
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index 02d7bdb..bbf8ef3 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -78,8 +78,10 @@
                                     PixelFormat format, Dataspace dataspace);
     void setPowerMode_2_2(Display display, IComposerClient::PowerMode mode);
     void setReadbackBuffer(Display display, const native_handle_t* buffer, int32_t releaseFence);
-    void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
-                                     Dataspace* outDataspace);
+    void getRequiredReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
+                                             Dataspace* outDataspace);
+    Error getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
+                                      Dataspace* outDataspace);
     void getReadbackBufferFence(Display display, int32_t* outFence);
 
     std::vector<ColorMode> getColorModes(Display display);
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
index 58efde9..7100297 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
@@ -34,6 +34,8 @@
 namespace V2_2 {
 namespace vts {
 
+using android::GraphicBuffer;
+using android::sp;
 using android::hardware::hidl_handle;
 using common::V1_1::BufferUsage;
 using common::V1_1::Dataspace;
@@ -156,6 +158,13 @@
 
     static int32_t GetBytesPerPixel(PixelFormat pixelFormat);
 
+    static void fillBufferAndGetFence(const sp<GraphicBuffer>& graphicBuffer,
+                                      IComposerClient::Color desiredColor, int* fillFence);
+
+    static void fillBufferAndGetFence(const sp<GraphicBuffer>& graphicBuffer,
+                                      const std::vector<IComposerClient::Color>& desiredColors,
+                                      int* fillFence);
+
     static void fillBuffer(int32_t width, int32_t height, uint32_t stride, void* bufferData,
                            PixelFormat pixelFormat,
                            std::vector<IComposerClient::Color> desiredPixelColors);
@@ -166,40 +175,39 @@
     static void fillColorsArea(std::vector<IComposerClient::Color>& expectedColors, int32_t stride,
                                IComposerClient::Rect area, IComposerClient::Color color);
 
-    static bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace,
-                                  const Error error);
-
     static const std::vector<ColorMode> colorModes;
     static const std::vector<Dataspace> dataspaces;
 
-    static void compareColorBuffers(std::vector<IComposerClient::Color>& expectedColors,
-                                    void* bufferData, const uint32_t stride, const uint32_t width,
-                                    const uint32_t height, const PixelFormat pixelFormat);
+    static bool readbackSupported(PixelFormat pixelFormat, Dataspace dataspace, Error error);
+    static bool readbackSupported(PixelFormat pixelFormat, Dataspace dataspace);
+
+    static void createReadbackBuffer(uint32_t width, uint32_t height, PixelFormat pixelFormat,
+                                     Dataspace dataspace, sp<GraphicBuffer>* graphicBuffer);
+
+    static void compareColorToBuffer(IComposerClient::Color expectedColors,
+                                     const sp<GraphicBuffer>& graphicBuffer, int32_t fence);
+
+    static void compareColorsToBuffer(std::vector<IComposerClient::Color>& expectedColors,
+                                      const sp<GraphicBuffer>& graphicBuffer, int32_t fence);
 };
 
 class ReadbackBuffer {
   public:
-    ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
-                   const std::shared_ptr<Gralloc>& gralloc, uint32_t width, uint32_t height,
-                   PixelFormat pixelFormat, Dataspace dataspace);
+    ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client, uint32_t width,
+                   uint32_t height, PixelFormat pixelFormat);
 
     void setReadbackBuffer();
 
     void checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors);
 
   protected:
+    sp<GraphicBuffer> mGraphicBuffer;
     uint32_t mWidth;
     uint32_t mHeight;
-    uint32_t mLayerCount;
-    PixelFormat mFormat;
-    uint64_t mUsage;
-    AccessRegion mAccessRegion;
-    uint32_t mStride;
-    std::unique_ptr<Gralloc::NativeHandleWrapper> mBufferHandle = nullptr;
     PixelFormat mPixelFormat;
-    Dataspace mDataspace;
+    uint32_t mLayerCount;
+    uint64_t mUsage;
     Display mDisplay;
-    std::shared_ptr<Gralloc> mGralloc;
     std::shared_ptr<ComposerClient> mComposerClient;
 };
 
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index e2a0f4d..5b8ce3f 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -40,7 +40,6 @@
 namespace {
 
 using android::Rect;
-using common::V1_1::BufferUsage;
 using common::V1_1::Dataspace;
 using common::V1_1::PixelFormat;
 using V2_1::Config;
@@ -100,8 +99,8 @@
 
         mTestRenderEngine->initGraphicBuffer(
                 static_cast<uint32_t>(mDisplayWidth), static_cast<uint32_t>(mDisplayHeight), 1,
-                static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                      BufferUsage::GPU_RENDER_TARGET));
+                GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN |
+                        GRALLOC_USAGE_HW_RENDER);
         mTestRenderEngine->setDisplaySettings(clientCompositionDisplay);
     }
 
@@ -116,6 +115,22 @@
         }
     }
 
+    sp<GraphicBuffer> allocateBuffer(uint32_t width, uint32_t height, uint32_t usage) {
+        const auto& graphicBuffer = sp<GraphicBuffer>::make(
+                width, height, android::PIXEL_FORMAT_RGBA_8888,
+                /*layerCount*/ 1u, usage, "VtsHalGraphicsComposer2_2_ReadbackTest");
+
+        if (graphicBuffer && android::OK == graphicBuffer->initCheck()) {
+            return nullptr;
+        }
+        return graphicBuffer;
+    }
+
+    sp<GraphicBuffer> allocateBuffer(uint32_t usage) {
+        return allocateBuffer(static_cast<uint32_t>(mDisplayWidth),
+                              static_cast<uint32_t>(mDisplayHeight), usage);
+    }
+
     void clearCommandReaderState() {
         mReader->mCompositionChanges.clear();
         mReader->mErrors.clear();
@@ -193,15 +208,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
@@ -220,8 +229,8 @@
         std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         writeLayers(layers);
@@ -255,15 +264,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
@@ -272,8 +275,8 @@
 
         mWriter->selectDisplay(mPrimaryDisplay);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
@@ -319,6 +322,155 @@
     }
 }
 
+TEST_P(GraphicsCompositionTest, SetLayerBufferWithSlotsToClear) {
+    Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                               &mDataspace);
+    if (error == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "Readback is unsupported";
+        return;
+    }
+    ASSERT_EQ(Error::NONE, error);
+
+    sp<GraphicBuffer> readbackBuffer;
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::createReadbackBuffer(
+            mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace, &readbackBuffer));
+    if (readbackBuffer == nullptr) {
+        GTEST_SUCCEED() << "Unsupported readback buffer attributes";
+        return;
+    }
+    // no fence needed for the readback buffer
+    int noFence = -1;
+
+    sp<GraphicBuffer> clearSlotBuffer = allocateBuffer(1u, 1u, GRALLOC_USAGE_HW_COMPOSER);
+    ASSERT_NE(nullptr, clearSlotBuffer);
+
+    // red buffer
+    uint32_t usage = GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN;
+    sp<GraphicBuffer> redBuffer = allocateBuffer(usage);
+    ASSERT_NE(nullptr, redBuffer);
+    int redFence;
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBufferAndGetFence(redBuffer, RED, &redFence));
+
+    // blue buffer
+    sp<GraphicBuffer> blueBuffer = allocateBuffer(usage);
+    ASSERT_NE(nullptr, blueBuffer);
+    int blueFence;
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBufferAndGetFence(blueBuffer, BLUE, &blueFence));
+
+    // layer defaults
+    IComposerClient::Rect rectFullDisplay = {0, 0, mDisplayWidth, mDisplayHeight};
+    Layer layer = mComposerClient->createLayer(mPrimaryDisplay, 3);
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerDisplayFrame(rectFullDisplay);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
+
+    // set the layer to the blue buffer
+    // should be blue
+    {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(
+                mPrimaryDisplay, readbackBuffer->handle, noFence));
+        mWriter->selectDisplay(mPrimaryDisplay);
+        mWriter->selectLayer(layer);
+        mWriter->setLayerBuffer(/*slot*/ 0, blueBuffer->handle, blueFence);
+        mWriter->validateDisplay();
+        execute();
+        ASSERT_TRUE(mReader->mCompositionChanges.empty());
+        ASSERT_TRUE(mReader->mErrors.size());
+        mWriter->selectDisplay(mPrimaryDisplay);
+        mWriter->presentDisplay();
+        execute();
+        int32_t fence;
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fence));
+        ASSERT_NO_FATAL_FAILURE(ReadbackHelper::compareColorToBuffer(BLUE, readbackBuffer, fence));
+    }
+
+    // change the layer to the red buffer
+    // should be red
+    {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(
+                mPrimaryDisplay, readbackBuffer->handle, noFence));
+        mWriter->selectDisplay(mPrimaryDisplay);
+        mWriter->selectLayer(layer);
+        mWriter->setLayerBuffer(/*slot*/ 1, redBuffer->handle, redFence);
+        mWriter->validateDisplay();
+        execute();
+        ASSERT_TRUE(mReader->mCompositionChanges.empty());
+        ASSERT_TRUE(mReader->mErrors.size());
+        mWriter->selectDisplay(mPrimaryDisplay);
+        mWriter->presentDisplay();
+        execute();
+        int32_t fence;
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fence));
+        ReadbackHelper::compareColorToBuffer(RED, readbackBuffer, fence);
+    }
+
+    // clear the slot for the blue buffer
+    // should still be red
+    {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(
+                mPrimaryDisplay, readbackBuffer->handle, noFence));
+        mWriter->selectDisplay(mPrimaryDisplay);
+        mWriter->selectLayer(layer);
+        mWriter->setLayerBuffer(/*slot*/ 0, clearSlotBuffer->handle, /*fence*/ -1);
+        mWriter->validateDisplay();
+        execute();
+        ASSERT_TRUE(mReader->mCompositionChanges.empty());
+        ASSERT_TRUE(mReader->mErrors.size());
+        mWriter->selectDisplay(mPrimaryDisplay);
+        mWriter->presentDisplay();
+        execute();
+        int32_t fence;
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fence));
+        ReadbackHelper::compareColorToBuffer(RED, readbackBuffer, fence);
+    }
+
+    // clear the slot for the red buffer, and set the buffer with the same slot to the blue buffer
+    // should be blue
+    {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(
+                mPrimaryDisplay, readbackBuffer->handle, noFence));
+        mWriter->selectDisplay(mPrimaryDisplay);
+        mWriter->selectLayer(layer);
+        mWriter->setLayerBuffer(/*slot*/ 1, clearSlotBuffer->handle, /*fence*/ -1);
+        mWriter->selectDisplay(mPrimaryDisplay);
+        mWriter->selectLayer(layer);
+        mWriter->setLayerBuffer(/*slot*/ 1, blueBuffer->handle, blueFence);
+        mWriter->validateDisplay();
+        execute();
+        ASSERT_TRUE(mReader->mCompositionChanges.empty());
+        ASSERT_TRUE(mReader->mErrors.size());
+        mWriter->selectDisplay(mPrimaryDisplay);
+        mWriter->presentDisplay();
+        execute();
+        int32_t fence;
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fence));
+        ReadbackHelper::compareColorToBuffer(BLUE, readbackBuffer, fence);
+    }
+
+    // clear the slot for the now-blue buffer
+    // should be black (no buffer)
+    // TODO(b/262037933) Ensure we never clear the active buffer's slot with the placeholder buffer
+    // by setting the layer to the color black
+    {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(
+                mPrimaryDisplay, readbackBuffer->handle, noFence));
+        mWriter->selectDisplay(mPrimaryDisplay);
+        mWriter->selectLayer(layer);
+        mWriter->setLayerBuffer(/*slot*/ 1, clearSlotBuffer->handle, /*fence*/ -1);
+        mWriter->validateDisplay();
+        execute();
+        ASSERT_TRUE(mReader->mCompositionChanges.empty());
+        ASSERT_TRUE(mReader->mErrors.size());
+        mWriter->selectDisplay(mPrimaryDisplay);
+        mWriter->presentDisplay();
+        execute();
+        int32_t fence;
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fence));
+        ReadbackHelper::compareColorToBuffer(BLACK, readbackBuffer, fence);
+    }
+}
+
 TEST_P(GraphicsCompositionTest, SetLayerBufferNoEffect) {
     for (ColorMode mode : mTestColorModes) {
         std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
@@ -327,15 +479,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
@@ -350,8 +496,7 @@
         layer->write(mWriter);
 
         // This following buffer call should have no effect
-        uint64_t usage =
-                static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN);
+        uint32_t usage = GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN;
         NativeHandleWrapper bufferHandle =
                 mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888, usage);
         mWriter->setLayerBuffer(0, bufferHandle.get(), -1);
@@ -360,8 +505,8 @@
         std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         mWriter->validateDisplay();
@@ -392,15 +537,11 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        PixelFormat pixelFormat;
+        Dataspace dataspace;
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat,
+                                                                   &dataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(pixelFormat, dataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
@@ -428,8 +569,8 @@
 
         std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(layers);
         ASSERT_EQ(0, mReader->mErrors.size());
@@ -441,9 +582,8 @@
             ASSERT_EQ(1, mReader->mCompositionChanges[0].second);
 
             PixelFormat clientFormat = PixelFormat::RGBA_8888;
-            uint64_t clientUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN |
-                                                         BufferUsage::CPU_WRITE_OFTEN |
-                                                         BufferUsage::COMPOSER_CLIENT_TARGET);
+            uint32_t clientUsage = GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN |
+                                   GRALLOC_USAGE_HW_FB;
             Dataspace clientDataspace = ReadbackHelper::getDataspaceForColorMode(mode);
             IComposerClient::Rect damage{0, 0, mDisplayWidth, mDisplayHeight};
 
@@ -510,15 +650,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
@@ -531,8 +665,8 @@
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
                                        {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, RED);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         auto deviceLayer = std::make_shared<TestBufferLayer>(
@@ -552,9 +686,8 @@
         deviceLayer->write(mWriter);
 
         PixelFormat clientFormat = PixelFormat::RGBA_8888;
-        uint64_t clientUsage =
-                static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                      BufferUsage::COMPOSER_CLIENT_TARGET);
+        uint32_t clientUsage =
+                GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_FB;
         Dataspace clientDataspace = ReadbackHelper::getDataspaceForColorMode(mode);
         int32_t clientWidth = mDisplayWidth;
         int32_t clientHeight = mDisplayHeight / 2;
@@ -633,15 +766,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
@@ -665,8 +792,8 @@
 
         std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         writeLayers(layers);
@@ -718,15 +845,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
@@ -742,8 +863,8 @@
 
         std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
 
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
@@ -779,15 +900,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
@@ -819,8 +934,8 @@
         // update expected colors to match crop
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
                                        {0, 0, mDisplayWidth, mDisplayHeight}, BLUE);
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(layers);
         ASSERT_EQ(0, mReader->mErrors.size());
@@ -850,15 +965,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
@@ -886,8 +995,8 @@
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE);
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         writeLayers(layers);
@@ -1019,15 +1128,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
@@ -1043,8 +1146,8 @@
         setUpLayers(IComposerClient::BlendMode::NONE);
         setExpectedColors(expectedColors);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(mLayers);
         ASSERT_EQ(0, mReader->mErrors.size());
@@ -1077,15 +1180,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
@@ -1102,8 +1199,8 @@
         setUpLayers(IComposerClient::BlendMode::COVERAGE);
         setExpectedColors(expectedColors);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(mLayers);
         ASSERT_EQ(0, mReader->mErrors.size());
@@ -1130,15 +1227,9 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
@@ -1153,8 +1244,8 @@
         setUpLayers(IComposerClient::BlendMode::PREMULTIPLIED);
         setExpectedColors(expectedColors);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(mLayers);
         ASSERT_EQ(0, mReader->mErrors.size());
@@ -1222,22 +1313,16 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
             return;
         }
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         mLayer->setTransform(Transform::FLIP_H);
         mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
@@ -1277,22 +1362,16 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
             return;
         }
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         mLayer->setTransform(Transform::FLIP_V);
@@ -1332,22 +1411,16 @@
         ASSERT_NO_FATAL_FAILURE(
                 mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-                mPrimaryDisplay,
-                [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                    mHasReadbackBuffer = ReadbackHelper::readbackSupported(tmpPixelFormat,
-                                                                           tmpDataspace, tmpError);
-                    mPixelFormat = tmpPixelFormat;
-                    mDataspace = tmpDataspace;
-                });
-
+        Error error = mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &mPixelFormat,
+                                                                   &mDataspace);
+        mHasReadbackBuffer = ReadbackHelper::readbackSupported(mPixelFormat, mDataspace, error);
         if (!mHasReadbackBuffer) {
             std::cout << "Readback not supported or unsupported pixelFormat/dataspace" << std::endl;
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
             return;
         }
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
-                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         mLayer->setTransform(Transform::ROT_180);
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 7e25a2e..f8fbb04 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -23,6 +23,7 @@
 #include <composer-vts/2.1/TestCommandReader.h>
 #include <composer-vts/2.2/ComposerVts.h>
 #include <gtest/gtest.h>
+#include <hardware/gralloc.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
 #include <mapper-vts/2.0/MapperVts.h>
@@ -35,7 +36,6 @@
 namespace vts {
 namespace {
 
-using common::V1_0::BufferUsage;
 using common::V1_1::ColorMode;
 using common::V1_1::Dataspace;
 using common::V1_1::PixelFormat;
@@ -65,17 +65,13 @@
         mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
         mComposerCallback->setVsyncAllowed(false);
 
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-            mPrimaryDisplay,
-            [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
-                mHasReadbackBuffer = tmpError == Error::NONE;
-                if (mHasReadbackBuffer) {
-                    mReadbackPixelFormat = tmpPixelFormat;
-                    mReadbackDataspace = tmpDataspace;
-                    ASSERT_LT(static_cast<PixelFormat>(0), mReadbackPixelFormat);
-                    ASSERT_NE(Dataspace::UNKNOWN, mReadbackDataspace);
-                }
-            });
+        Error error = mComposerClient->getReadbackBufferAttributes(
+                mPrimaryDisplay, &mReadbackPixelFormat, &mReadbackDataspace);
+        mHasReadbackBuffer = error == Error::NONE;
+        if (mHasReadbackBuffer) {
+            ASSERT_LT(static_cast<PixelFormat>(0), mReadbackPixelFormat);
+            ASSERT_NE(Dataspace::UNKNOWN, mReadbackDataspace);
+        }
 
         mInvalidDisplayId = GetInvalidDisplayId();
     }
@@ -153,10 +149,9 @@
     }
 
     NativeHandleWrapper allocate() {
-        uint64_t usage =
-                static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
         return mGralloc->allocate(/*width*/ 64, /*height*/ 64, /*layerCount*/ 1,
-                                  PixelFormat::RGBA_8888, usage);
+                                  PixelFormat::RGBA_8888,
+                                  GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN);
     }
 
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
@@ -434,9 +429,7 @@
     }
 
     // BufferUsage::COMPOSER_OUTPUT is missing
-    uint64_t usage =
-            static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
-
+    uint64_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_SW_READ_OFTEN;
     std::unique_ptr<Gralloc> gralloc;
     std::unique_ptr<NativeHandleWrapper> buffer;
     ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
@@ -457,9 +450,7 @@
         return;
     }
 
-    uint64_t usage =
-            static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
-
+    uint64_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_SW_READ_OFTEN;
     std::unique_ptr<Gralloc> gralloc;
     std::unique_ptr<NativeHandleWrapper> buffer;
     ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
diff --git a/graphics/composer/aidl/vts/ReadbackVts.cpp b/graphics/composer/aidl/vts/ReadbackVts.cpp
index abb58e2..b59793f 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.cpp
+++ b/graphics/composer/aidl/vts/ReadbackVts.cpp
@@ -20,6 +20,8 @@
 #include "renderengine/ExternalTexture.h"
 #include "renderengine/impl/ExternalTexture.h"
 
+using ::android::status_t;
+
 namespace aidl::android::hardware::graphics::composer3::vts {
 
 const std::vector<ColorMode> ReadbackHelper::colorModes = {ColorMode::SRGB, ColorMode::DISPLAY_P3};
@@ -27,6 +29,9 @@
                                                            common::Dataspace::DISPLAY_P3};
 
 void TestLayer::write(ComposerClientWriter& writer) {
+    ::android::status_t status = ::android::OK;
+    ASSERT_EQ(::android::OK, status);
+
     writer.setLayerDisplayFrame(mDisplay, mLayer, mDisplayFrame);
     writer.setLayerSourceCrop(mDisplay, mLayer, mSourceCrop);
     writer.setLayerZOrder(mDisplay, mLayer, mZOrder);
@@ -37,6 +42,40 @@
     writer.setLayerBrightness(mDisplay, mLayer, mBrightness);
 }
 
+bool ReadbackHelper::readbackSupported(const common::PixelFormat& pixelFormat,
+                                       const common::Dataspace& dataspace) {
+    // TODO: add support for RGBA_1010102
+    if (pixelFormat != common::PixelFormat::RGB_888 &&
+        pixelFormat != common::PixelFormat::RGBA_8888) {
+        return false;
+    }
+    if (std::find(dataspaces.begin(), dataspaces.end(), dataspace) == dataspaces.end()) {
+        return false;
+    }
+    return true;
+}
+
+void ReadbackHelper::createReadbackBuffer(ReadbackBufferAttributes readbackBufferAttributes,
+                                          const VtsDisplay& display,
+                                          sp<GraphicBuffer>* graphicBuffer) {
+    ASSERT_NE(nullptr, graphicBuffer);
+    if (!readbackSupported(readbackBufferAttributes.format, readbackBufferAttributes.dataspace)) {
+        *graphicBuffer = nullptr;
+    }
+    uint64_t usage =
+            static_cast<uint64_t>(static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
+                                  static_cast<uint64_t>(common::BufferUsage::GPU_TEXTURE));
+
+    uint32_t layerCount = 1;
+    *graphicBuffer = sp<GraphicBuffer>::make(
+            static_cast<uint32_t>(display.getDisplayWidth()),
+            static_cast<uint32_t>(display.getDisplayHeight()),
+            static_cast<::android::PixelFormat>(readbackBufferAttributes.format), layerCount, usage,
+            "ReadbackBuffer");
+    ASSERT_NE(nullptr, *graphicBuffer);
+    ASSERT_EQ(::android::OK, (*graphicBuffer)->initCheck());
+}
+
 std::string ReadbackHelper::getColorModeString(ColorMode mode) {
     switch (mode) {
         case ColorMode::SRGB:
@@ -103,11 +142,11 @@
     return layerSettings;
 }
 
-int32_t ReadbackHelper::GetBytesPerPixel(common::PixelFormat pixelFormat) {
+int32_t ReadbackHelper::GetBytesPerPixel(PixelFormat pixelFormat) {
     switch (pixelFormat) {
-        case common::PixelFormat::RGBA_8888:
+        case PixelFormat::RGBA_8888:
             return 4;
-        case common::PixelFormat::RGB_888:
+        case PixelFormat::RGB_888:
             return 3;
         default:
             return -1;
@@ -116,136 +155,161 @@
 
 void ReadbackHelper::fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData,
                                 common::PixelFormat pixelFormat,
-                                std::vector<Color> desiredPixelColors) {
+                                const std::vector<Color>& desiredColors) {
     ASSERT_TRUE(pixelFormat == common::PixelFormat::RGB_888 ||
                 pixelFormat == common::PixelFormat::RGBA_8888);
     int32_t bytesPerPixel = 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;
-            Color srcColor = desiredPixelColors[static_cast<size_t>(pixel)];
+            int pixel = row * static_cast<int32_t>(width) + col;
+            Color desiredColor = desiredColors[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));
+            pixelColor[0] = static_cast<uint8_t>(std::round(255.0f * desiredColor.r));
+            pixelColor[1] = static_cast<uint8_t>(std::round(255.0f * desiredColor.g));
+            pixelColor[2] = static_cast<uint8_t>(std::round(255.0f * desiredColor.b));
 
             if (bytesPerPixel == 4) {
-                pixelColor[3] = static_cast<uint8_t>(std::round(255.0f * srcColor.a));
+                pixelColor[3] = static_cast<uint8_t>(std::round(255.0f * desiredColor.a));
             }
         }
     }
 }
 
-void ReadbackHelper::clearColors(std::vector<Color>& expectedColors, int32_t width, int32_t height,
+void ReadbackHelper::clearColors(std::vector<Color>& colors, int32_t width, int32_t height,
                                  int32_t displayWidth) {
     for (int row = 0; row < height; row++) {
         for (int col = 0; col < width; col++) {
             int pixel = row * displayWidth + col;
-            expectedColors[static_cast<size_t>(pixel)] = BLACK;
+            colors[static_cast<size_t>(pixel)] = BLACK;
         }
     }
 }
 
-void ReadbackHelper::fillColorsArea(std::vector<Color>& expectedColors, int32_t stride, Rect area,
-                                    Color color) {
+void ReadbackHelper::fillColorsArea(std::vector<Color>& colors, int32_t stride, Rect area,
+                                    Color desiredColor) {
     for (int row = area.top; row < area.bottom; row++) {
         for (int col = area.left; col < area.right; col++) {
             int pixel = row * stride + col;
-            expectedColors[static_cast<size_t>(pixel)] = color;
+            colors[static_cast<size_t>(pixel)] = desiredColor;
         }
     }
 }
 
-bool ReadbackHelper::readbackSupported(const common::PixelFormat& pixelFormat,
-                                       const common::Dataspace& dataspace) {
-    if (pixelFormat != common::PixelFormat::RGB_888 &&
-        pixelFormat != common::PixelFormat::RGBA_8888) {
-        return false;
-    }
-    if (std::find(dataspaces.begin(), dataspaces.end(), dataspace) == dataspaces.end()) {
-        return false;
-    }
-    return true;
+void ReadbackHelper::fillBufferAndGetFence(const sp<GraphicBuffer>& graphicBuffer,
+                                           Color desiredColor, int* fillFence) {
+    ASSERT_NE(nullptr, fillFence);
+    std::vector<Color> desiredColors(
+            static_cast<size_t>(graphicBuffer->getWidth() * graphicBuffer->getHeight()));
+    ::android::Rect bounds = graphicBuffer->getBounds();
+    fillColorsArea(desiredColors, static_cast<int32_t>(graphicBuffer->getWidth()),
+                   {bounds.left, bounds.top, bounds.right, bounds.bottom}, desiredColor);
+    ASSERT_NO_FATAL_FAILURE(fillBufferAndGetFence(graphicBuffer, desiredColors, fillFence));
 }
 
-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);
+void ReadbackHelper::fillBufferAndGetFence(const sp<GraphicBuffer>& graphicBuffer,
+                                           const std::vector<Color>& desiredColors,
+                                           int* fillFence) {
+    ASSERT_TRUE(graphicBuffer->getPixelFormat() == ::android::PIXEL_FORMAT_RGB_888 ||
+                graphicBuffer->getPixelFormat() == ::android::PIXEL_FORMAT_RGBA_8888);
+    void* bufData;
+    int32_t bytesPerPixel = -1;
+    int32_t bytesPerStride = -1;
+    status_t status =
+            graphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                &bufData, &bytesPerPixel, &bytesPerStride);
+    ASSERT_EQ(::android::OK, status);
+
+    const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
+                                    ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
+                                    : graphicBuffer->getStride();
+    ReadbackHelper::fillBuffer(
+            graphicBuffer->getWidth(), graphicBuffer->getHeight(), stride, bufData,
+            static_cast<common::PixelFormat>(graphicBuffer->getPixelFormat()), desiredColors);
+    status = graphicBuffer->unlockAsync(fillFence);
+    ASSERT_EQ(::android::OK, status);
+}
+
+void ReadbackHelper::compareColorToBuffer(Color expectedColor,
+                                          const sp<GraphicBuffer>& graphicBuffer,
+                                          const ndk::ScopedFileDescriptor& fence) {
+    std::vector<Color> expectedColors(
+            static_cast<size_t>(graphicBuffer->getWidth() * graphicBuffer->getHeight()));
+    ::android::Rect bounds = graphicBuffer->getBounds();
+    fillColorsArea(expectedColors, static_cast<int32_t>(graphicBuffer->getWidth()),
+                   {bounds.left, bounds.top, bounds.right, bounds.bottom}, expectedColor);
+    compareColorsToBuffer(expectedColors, graphicBuffer, fence);
+}
+
+void ReadbackHelper::compareColorsToBuffer(const std::vector<Color>& expectedColors,
+                                           const sp<GraphicBuffer>& graphicBuffer,
+                                           const ndk::ScopedFileDescriptor& fence) {
+    ASSERT_TRUE(graphicBuffer->getPixelFormat() == ::android::PIXEL_FORMAT_RGB_888 ||
+                graphicBuffer->getPixelFormat() == ::android::PIXEL_FORMAT_RGBA_8888);
+
+    int bytesPerPixel = -1;
+    int bytesPerStride = -1;
+    void* bufData = nullptr;
+    status_t status = graphicBuffer->lockAsync(GRALLOC_USAGE_SW_READ_OFTEN, &bufData,
+                                               dup(fence.get()), &bytesPerPixel, &bytesPerStride);
+    ASSERT_EQ(::android::OK, status);
+
+    const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
+                                    ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
+                                    : graphicBuffer->getStride();
+
+    if (bytesPerPixel == -1) {
+        bytesPerPixel = ReadbackHelper::GetBytesPerPixel(
+                static_cast<PixelFormat>(graphicBuffer->getPixelFormat()));
+    }
     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;
+    for (int row = 0; row < graphicBuffer->getHeight(); row++) {
+        for (int col = 0; col < graphicBuffer->getWidth(); col++) {
+            int pixel = row * static_cast<int32_t>(graphicBuffer->getWidth()) + col;
             int offset = (row * static_cast<int32_t>(stride) + col) * bytesPerPixel;
-            uint8_t* pixelColor = (uint8_t*)bufferData + offset;
+            uint8_t* pixelColor = (uint8_t*)bufData + offset;
             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]);
         }
     }
+
+    status = graphicBuffer->unlock();
+    ASSERT_EQ(::android::OK, status);
 }
 
 ReadbackBuffer::ReadbackBuffer(int64_t display, const std::shared_ptr<VtsComposerClient>& client,
-                               int32_t width, int32_t height, common::PixelFormat pixelFormat,
-                               common::Dataspace dataspace)
+                               int32_t width, int32_t height, common::PixelFormat pixelFormat)
     : mComposerClient(client) {
     mDisplay = display;
-
-    mPixelFormat = pixelFormat;
-    mDataspace = dataspace;
-
     mWidth = static_cast<uint32_t>(width);
     mHeight = static_cast<uint32_t>(height);
+    mPixelFormat = pixelFormat;
     mLayerCount = 1;
     mUsage = static_cast<uint64_t>(static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
                                    static_cast<uint64_t>(common::BufferUsage::GPU_TEXTURE));
-
-    mAccessRegion.top = 0;
-    mAccessRegion.left = 0;
-    mAccessRegion.right = static_cast<int32_t>(width);
-    mAccessRegion.bottom = static_cast<int32_t>(height);
-}
-
-::android::sp<::android::GraphicBuffer> ReadbackBuffer::allocateBuffer() {
-    return ::android::sp<::android::GraphicBuffer>::make(
-            mWidth, mHeight, static_cast<::android::PixelFormat>(mPixelFormat), mLayerCount, mUsage,
-            "ReadbackBuffer");
 }
 
 void ReadbackBuffer::setReadbackBuffer() {
-    mGraphicBuffer = allocateBuffer();
+    mGraphicBuffer = sp<GraphicBuffer>::make(mWidth, mHeight,
+                                             static_cast<::android::PixelFormat>(mPixelFormat),
+                                             mLayerCount, mUsage, "ReadbackBuffer");
     ASSERT_NE(nullptr, mGraphicBuffer);
     ASSERT_EQ(::android::OK, mGraphicBuffer->initCheck());
-    const auto& bufferHandle = mGraphicBuffer->handle;
-    ::ndk::ScopedFileDescriptor fence = ::ndk::ScopedFileDescriptor(-1);
-    EXPECT_TRUE(mComposerClient->setReadbackBuffer(mDisplay, bufferHandle, fence).isOk());
+    ::ndk::ScopedFileDescriptor noFence = ::ndk::ScopedFileDescriptor(-1);
+    const auto& status =
+            mComposerClient->setReadbackBuffer(mDisplay, mGraphicBuffer->handle, noFence);
+    ASSERT_TRUE(status.isOk());
 }
 
 void ReadbackBuffer::checkReadbackBuffer(const std::vector<Color>& expectedColors) {
-    ASSERT_NE(nullptr, mGraphicBuffer);
     // lock buffer for reading
     const auto& [fenceStatus, bufferFence] = mComposerClient->getReadbackBufferFence(mDisplay);
-    EXPECT_TRUE(fenceStatus.isOk());
-
-    int bytesPerPixel = -1;
-    int bytesPerStride = -1;
-    void* bufData = nullptr;
-
-    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);
-    const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
-                                    ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
-                                    : mGraphicBuffer->getStride();
-    ReadbackHelper::compareColorBuffers(expectedColors, bufData, stride, mWidth, mHeight,
-                                        mPixelFormat);
-    status = mGraphicBuffer->unlock();
-    EXPECT_EQ(::android::OK, status);
+    ASSERT_TRUE(fenceStatus.isOk());
+    ReadbackHelper::compareColorsToBuffer(expectedColors, mGraphicBuffer, bufferFence);
 }
 
 void TestColorLayer::write(ComposerClientWriter& writer) {
@@ -323,9 +387,8 @@
     const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
                                     ? 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_EQ(::android::OK, status);
+    ReadbackHelper::fillBuffer(mWidth, mHeight, stride, bufData, mPixelFormat, expectedColors);
 
     const auto unlockStatus = mGraphicBuffer->unlockAsync(&mFillFence);
     ASSERT_EQ(::android::OK, unlockStatus);
@@ -335,13 +398,13 @@
     mGraphicBuffer = allocateBuffer();
     ASSERT_NE(nullptr, mGraphicBuffer);
     ASSERT_EQ(::android::OK, mGraphicBuffer->initCheck());
-    ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
+    fillBuffer(colors);
 }
 
-::android::sp<::android::GraphicBuffer> TestBufferLayer::allocateBuffer() {
-    return ::android::sp<::android::GraphicBuffer>::make(
-            mWidth, mHeight, static_cast<::android::PixelFormat>(mPixelFormat), mLayerCount, mUsage,
-            "TestBufferLayer");
+sp<GraphicBuffer> TestBufferLayer::allocateBuffer() {
+    return sp<GraphicBuffer>::make(mWidth, mHeight,
+                                   static_cast<::android::PixelFormat>(mPixelFormat), mLayerCount,
+                                   mUsage, "TestBufferLayer");
 }
 
 void TestBufferLayer::setDataspace(common::Dataspace dataspace, ComposerClientWriter& writer) {
diff --git a/graphics/composer/aidl/vts/ReadbackVts.h b/graphics/composer/aidl/vts/ReadbackVts.h
index ee9f0d5..ecf0d52 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.h
+++ b/graphics/composer/aidl/vts/ReadbackVts.h
@@ -33,6 +33,8 @@
 using common::Dataspace;
 using common::PixelFormat;
 using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
+using ::android::GraphicBuffer;
+using ::android::sp;
 
 static const Color BLACK = {0.0f, 0.0f, 0.0f, 1.0f};
 static const Color RED = {1.0f, 0.0f, 0.0f, 1.0f};
@@ -146,7 +148,7 @@
 
   protected:
     Composition mComposition;
-    ::android::sp<::android::GraphicBuffer> mGraphicBuffer;
+    sp<GraphicBuffer> mGraphicBuffer;
     TestRenderEngine& mRenderEngine;
     int32_t mFillFence;
     uint32_t mWidth;
@@ -162,6 +164,11 @@
 
 class ReadbackHelper {
   public:
+    static bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace);
+
+    static void createReadbackBuffer(ReadbackBufferAttributes readbackBufferAttributes,
+                                     const VtsDisplay& display, sp<GraphicBuffer>* graphicBuffer);
+
     static std::string getColorModeString(ColorMode mode);
 
     static std::string getDataspaceString(Dataspace dataspace);
@@ -171,28 +178,36 @@
     static int32_t GetBytesPerPixel(PixelFormat pixelFormat);
 
     static void fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData,
-                           PixelFormat pixelFormat, std::vector<Color> desiredPixelColors);
+                           PixelFormat pixelFormat, const std::vector<Color>& desriedColors);
 
-    static void clearColors(std::vector<Color>& expectedColors, int32_t width, int32_t height,
+    static void clearColors(std::vector<Color>& colors, int32_t width, int32_t height,
                             int32_t displayWidth);
 
-    static void fillColorsArea(std::vector<Color>& expectedColors, int32_t stride, Rect area,
-                               Color color);
+    static void fillColorsArea(std::vector<Color>& colors, int32_t stride, Rect area,
+                               Color desiredColor);
 
-    static bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace);
+    static void fillBufferAndGetFence(const sp<GraphicBuffer>& buffer, Color desiredColor,
+                                      int* fillFence);
+
+    static void fillBufferAndGetFence(const sp<GraphicBuffer>& buffer,
+                                      const std::vector<Color>& desiredColors, int* fillFence);
+
+    static void compareColorToBuffer(
+            Color expectedColor, const sp<GraphicBuffer>& graphicBuffer,
+            const ndk::ScopedFileDescriptor& fence = ::ndk::ScopedFileDescriptor(-1));
+
+    static void compareColorsToBuffer(
+            const std::vector<Color>& expectedColors, const sp<GraphicBuffer>& graphicBuffer,
+            const ndk::ScopedFileDescriptor& fence = ::ndk::ScopedFileDescriptor(-1));
 
     static const std::vector<ColorMode> colorModes;
     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);
 };
 
 class ReadbackBuffer {
   public:
     ReadbackBuffer(int64_t display, const std::shared_ptr<VtsComposerClient>& client, int32_t width,
-                   int32_t height, common::PixelFormat pixelFormat, common::Dataspace dataspace);
+                   int32_t height, common::PixelFormat pixelFormat);
 
     void setReadbackBuffer();
 
@@ -201,18 +216,12 @@
   protected:
     uint32_t mWidth;
     uint32_t mHeight;
+    PixelFormat mPixelFormat;
     uint32_t mLayerCount;
     uint32_t mUsage;
-    PixelFormat mPixelFormat;
-    Dataspace mDataspace;
     int64_t mDisplay;
-    ::android::sp<::android::GraphicBuffer> mGraphicBuffer;
+    sp<GraphicBuffer> mGraphicBuffer;
     std::shared_ptr<VtsComposerClient> mComposerClient;
-    ::android::Rect mAccessRegion;
-    native_handle_t mBufferHandle;
-
-  private:
-    ::android::sp<::android::GraphicBuffer> allocateBuffer();
 };
 
 }  // namespace aidl::android::hardware::graphics::composer3::vts
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.cpp b/graphics/composer/aidl/vts/RenderEngineVts.cpp
index 66779c8..b84d0d0 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.cpp
+++ b/graphics/composer/aidl/vts/RenderEngineVts.cpp
@@ -76,18 +76,7 @@
 }
 
 void TestRenderEngine::checkColorBuffer(const std::vector<Color>& expectedColors) {
-    void* bufferData;
-    int32_t bytesPerPixel = -1;
-    int32_t bytesPerStride = -1;
-    ASSERT_EQ(0, mGraphicBuffer->lock(static_cast<uint32_t>(mGraphicBuffer->getUsage()),
-                                      &bufferData, &bytesPerPixel, &bytesPerStride));
-    const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0)
-                                    ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
-                                    : mGraphicBuffer->getStride();
-    ReadbackHelper::compareColorBuffers(expectedColors, bufferData, stride,
-                                        mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight(),
-                                        mFormat);
-    ASSERT_EQ(::android::OK, mGraphicBuffer->unlock());
+    ReadbackHelper::compareColorsToBuffer(expectedColors, mGraphicBuffer);
 }
 
 }  // namespace aidl::android::hardware::graphics::composer3::vts
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 6fa3392..93d9693 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -18,7 +18,6 @@
 
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
-#include <aidl/android/hardware/graphics/common/BufferUsage.h>
 #include <aidl/android/hardware/graphics/composer3/IComposer.h>
 #include <gtest/gtest.h>
 #include <ui/DisplayId.h>
@@ -81,13 +80,11 @@
         clientCompositionDisplay.physicalDisplay = Rect(getDisplayWidth(), getDisplayHeight());
         clientCompositionDisplay.clip = clientCompositionDisplay.physicalDisplay;
 
-        mTestRenderEngine->initGraphicBuffer(
-                static_cast<uint32_t>(getDisplayWidth()), static_cast<uint32_t>(getDisplayHeight()),
-                /*layerCount*/ 1U,
-                static_cast<uint64_t>(
-                        static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
-                        static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
-                        static_cast<uint64_t>(common::BufferUsage::GPU_RENDER_TARGET)));
+        mTestRenderEngine->initGraphicBuffer(static_cast<uint32_t>(getDisplayWidth()),
+                                             static_cast<uint32_t>(getDisplayHeight()),
+                                             /*layerCount*/ 1U,
+                                             GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_SW_READ_OFTEN |
+                                                     GRALLOC_USAGE_SW_WRITE_OFTEN);
         mTestRenderEngine->setDisplaySettings(clientCompositionDisplay);
     }
 
@@ -115,18 +112,21 @@
         ASSERT_EQ(status.getServiceSpecificError(), serviceSpecificError);
     }
 
-    std::pair<bool, ::android::sp<::android::GraphicBuffer>> allocateBuffer(uint32_t usage) {
-        const auto width = static_cast<uint32_t>(getDisplayWidth());
-        const auto height = static_cast<uint32_t>(getDisplayHeight());
-
-        const auto& graphicBuffer = ::android::sp<::android::GraphicBuffer>::make(
-                width, height, ::android::PIXEL_FORMAT_RGBA_8888,
-                /*layerCount*/ 1u, usage, "VtsHalGraphicsComposer3_ReadbackTest");
+    sp<GraphicBuffer> allocateBuffer(uint32_t width, uint32_t height, uint64_t usage) {
+        sp<GraphicBuffer> graphicBuffer =
+                sp<GraphicBuffer>::make(width, height, ::android::PIXEL_FORMAT_RGBA_8888,
+                                        /*layerCount*/ 1u, static_cast<uint32_t>(usage),
+                                        "VtsHalGraphicsComposer3_ReadbackTest");
 
         if (graphicBuffer && ::android::OK == graphicBuffer->initCheck()) {
-            return {true, graphicBuffer};
+            return graphicBuffer;
         }
-        return {false, graphicBuffer};
+        return nullptr;
+    }
+
+    sp<GraphicBuffer> allocateBuffer(uint64_t usage) {
+        return allocateBuffer(static_cast<uint32_t>(getDisplayWidth()),
+                              static_cast<uint32_t>(getDisplayHeight()), usage);
     }
 
     uint64_t getStableDisplayId(int64_t display) {
@@ -293,7 +293,7 @@
         ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), coloredSquare, BLUE);
 
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         writeLayers(layers);
@@ -332,7 +332,7 @@
         }
 
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         std::vector<Color> expectedColors(
                 static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
@@ -378,6 +378,143 @@
     }
 }
 
+TEST_P(GraphicsCompositionTest, SetLayerBufferWithSlotsToClear) {
+    const auto& [status, readbackBufferAttributes] =
+            mComposerClient->getReadbackBufferAttributes(getPrimaryDisplayId());
+    if (!status.isOk()) {
+        GTEST_SUCCEED() << "Readback not supported";
+        return;
+    }
+
+    sp<GraphicBuffer> readbackBuffer;
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::createReadbackBuffer(
+            readbackBufferAttributes, getPrimaryDisplay(), &readbackBuffer));
+    if (readbackBuffer == nullptr) {
+        GTEST_SUCCEED() << "Unsupported readback buffer attributes";
+        return;
+    }
+    // no fence needed for the readback buffer
+    ScopedFileDescriptor noFence(-1);
+
+    sp<GraphicBuffer> clearSlotBuffer = allocateBuffer(1u, 1u, GRALLOC_USAGE_HW_COMPOSER);
+    ASSERT_NE(nullptr, clearSlotBuffer);
+
+    // red buffer
+    uint64_t usage = GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN;
+    sp<GraphicBuffer> redBuffer = allocateBuffer(usage);
+    ASSERT_NE(nullptr, redBuffer);
+    int redFence;
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBufferAndGetFence(redBuffer, RED, &redFence));
+
+    // blue buffer
+    sp<GraphicBuffer> blueBuffer = allocateBuffer(usage);
+    ASSERT_NE(nullptr, blueBuffer);
+    int blueFence;
+    ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBufferAndGetFence(blueBuffer, BLUE, &blueFence));
+
+    // layer defaults
+    common::Rect rectFullDisplay = {0, 0, getDisplayWidth(), getDisplayHeight()};
+    int64_t display = getPrimaryDisplayId();
+    auto [layerStatus, layer] = mComposerClient->createLayer(getPrimaryDisplayId(), 3);
+    ASSERT_TRUE(layerStatus.isOk());
+    mWriter->setLayerDisplayFrame(display, layer, rectFullDisplay);
+    mWriter->setLayerCompositionType(display, layer, Composition::DEVICE);
+
+    // set the layer to the blue buffer
+    // should be blue
+    {
+        auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
+        ASSERT_TRUE(status.isOk());
+        mWriter->setLayerBuffer(display, layer, /*slot*/ 0, blueBuffer->handle, blueFence);
+        mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
+        execute();
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(display).empty());
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter->presentDisplay(display);
+        execute();
+        auto [fenceStatus, fence] = mComposerClient->getReadbackBufferFence(display);
+        ASSERT_TRUE(fenceStatus.isOk());
+        ReadbackHelper::compareColorToBuffer(BLUE, readbackBuffer, fence);
+    }
+
+    // change the layer to the red buffer
+    // should be red
+    {
+        auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
+        ASSERT_TRUE(status.isOk());
+        mWriter->setLayerBuffer(display, layer, /*slot*/ 1, redBuffer->handle, redFence);
+        mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
+        execute();
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(display).empty());
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter->presentDisplay(display);
+        execute();
+        auto [fenceStatus, fence] = mComposerClient->getReadbackBufferFence(display);
+        ASSERT_TRUE(fenceStatus.isOk());
+        ReadbackHelper::compareColorToBuffer(RED, readbackBuffer, fence);
+    }
+
+    // clear the slot for the blue buffer
+    // should still be red
+    {
+        auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
+        ASSERT_TRUE(status.isOk());
+        mWriter->setLayerBufferWithNewCommand(display, layer, /*slot*/ 0, clearSlotBuffer->handle,
+                                              /*fence*/ -1);
+        mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
+        execute();
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(display).empty());
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter->presentDisplay(display);
+        execute();
+        auto [fenceStatus, fence] = mComposerClient->getReadbackBufferFence(display);
+        ASSERT_TRUE(fenceStatus.isOk());
+        ReadbackHelper::compareColorToBuffer(RED, readbackBuffer, fence);
+    }
+
+    // clear the slot for the red buffer, and set the buffer with the same slot to the blue buffer
+    // should be blue
+    {
+        auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
+        ASSERT_TRUE(status.isOk());
+        mWriter->setLayerBufferWithNewCommand(display, layer, /*slot*/ 1, clearSlotBuffer->handle,
+                                              /*fence*/ -1);
+        mWriter->setLayerBuffer(display, layer, /*slot*/ 1, blueBuffer->handle, blueFence);
+        mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
+        execute();
+        ASSERT_TRUE(mReader.takeChangedCompositionTypes(display).empty());
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter->presentDisplay(display);
+        execute();
+        auto [fenceStatus, fence] = mComposerClient->getReadbackBufferFence(display);
+        ASSERT_TRUE(fenceStatus.isOk());
+        ReadbackHelper::compareColorToBuffer(BLUE, readbackBuffer, fence);
+    }
+
+    // clear the slot for the now-blue buffer
+    // should be black (no buffer)
+    // TODO(b/262037933) Ensure we never clear the active buffer's slot with the placeholder buffer
+    // by setting the layer to the color black
+    {
+        auto status = mComposerClient->setReadbackBuffer(display, readbackBuffer->handle, noFence);
+        ASSERT_TRUE(status.isOk());
+        mWriter->setLayerBufferWithNewCommand(display, layer, /*slot*/ 1, clearSlotBuffer->handle,
+                                              /*fence*/ -1);
+        mWriter->validateDisplay(display, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(display).empty()) {
+            GTEST_SUCCEED();
+            return;
+        }
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter->presentDisplay(display);
+        execute();
+        auto [fenceStatus, fence] = mComposerClient->getReadbackBufferFence(display);
+        ASSERT_TRUE(fenceStatus.isOk());
+        ReadbackHelper::compareColorToBuffer(BLACK, readbackBuffer, fence);
+    }
+}
+
 TEST_P(GraphicsCompositionTest, SetLayerBufferNoEffect) {
     for (ColorMode mode : mTestColorModes) {
         EXPECT_TRUE(mComposerClient
@@ -399,10 +536,9 @@
         layer->write(*mWriter);
 
         // This following buffer call should have no effect
-        const auto usage = static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
-                           static_cast<uint32_t>(common::BufferUsage::CPU_READ_OFTEN);
-        const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(usage);
-        ASSERT_TRUE(graphicBufferStatus);
+        uint64_t usage = GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN;
+        sp<GraphicBuffer> graphicBuffer = allocateBuffer(usage);
+        ASSERT_NE(nullptr, graphicBuffer);
         const auto& buffer = graphicBuffer->handle;
         mWriter->setLayerBuffer(getPrimaryDisplayId(), layer->getLayer(), /*slot*/ 0, buffer,
                                 /*acquireFence*/ -1);
@@ -413,7 +549,7 @@
         ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), coloredSquare, BLUE);
 
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
@@ -441,7 +577,7 @@
     }
 
     ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                  getDisplayHeight(), mPixelFormat, mDataspace);
+                                  getDisplayHeight(), mPixelFormat);
 
     ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 }
@@ -454,10 +590,9 @@
         return;
     }
 
-    const auto usage = static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
-                       static_cast<uint32_t>(common::BufferUsage::CPU_READ_OFTEN);
-    const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(usage);
-    ASSERT_TRUE(graphicBufferStatus);
+    uint64_t usage = GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN;
+    sp<GraphicBuffer> graphicBuffer = allocateBuffer(usage);
+    ASSERT_NE(nullptr, graphicBuffer);
     const auto& bufferHandle = graphicBuffer->handle;
     ::ndk::ScopedFileDescriptor fence = ::ndk::ScopedFileDescriptor(-1);
 
@@ -539,7 +674,7 @@
         std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(layers);
         ASSERT_TRUE(mReader.takeErrors().empty());
@@ -552,16 +687,14 @@
             ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0].composition);
 
             PixelFormat clientFormat = PixelFormat::RGBA_8888;
-            auto clientUsage = static_cast<uint32_t>(
-                    static_cast<uint32_t>(common::BufferUsage::CPU_READ_OFTEN) |
-                    static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
-                    static_cast<uint32_t>(common::BufferUsage::COMPOSER_CLIENT_TARGET));
+            auto clientUsage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_SW_READ_OFTEN |
+                               GRALLOC_USAGE_SW_WRITE_OFTEN;
             Dataspace clientDataspace = ReadbackHelper::getDataspaceForColorMode(mode);
             common::Rect damage{0, 0, getDisplayWidth(), getDisplayHeight()};
 
             // create client target buffer
-            const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(clientUsage);
-            ASSERT_TRUE(graphicBufferStatus);
+            sp<GraphicBuffer> graphicBuffer = allocateBuffer(clientUsage);
+            ASSERT_NE(nullptr, graphicBuffer);
             const auto& buffer = graphicBuffer->handle;
             void* clientBufData;
             const auto stride = static_cast<uint32_t>(graphicBuffer->stride);
@@ -618,7 +751,7 @@
                 {0, getDisplayHeight() / 2, getDisplayWidth(), getDisplayHeight()}, RED);
 
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         auto deviceLayer = std::make_shared<TestBufferLayer>(
@@ -637,10 +770,8 @@
         deviceLayer->write(*mWriter);
 
         PixelFormat clientFormat = PixelFormat::RGBA_8888;
-        auto clientUsage = static_cast<uint32_t>(
-                static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
-                static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
-                static_cast<uint32_t>(common::BufferUsage::COMPOSER_CLIENT_TARGET));
+        auto clientUsage =
+                GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
         Dataspace clientDataspace = ReadbackHelper::getDataspaceForColorMode(mode);
         int32_t clientWidth = getDisplayWidth();
         int32_t clientHeight = getDisplayHeight() / 2;
@@ -662,8 +793,8 @@
         }
         // create client target buffer
         ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0].composition);
-        const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(clientUsage);
-        ASSERT_TRUE(graphicBufferStatus);
+        sp<GraphicBuffer> graphicBuffer = allocateBuffer(clientUsage);
+        ASSERT_NE(nullptr, graphicBuffer);
         const auto& buffer = graphicBuffer->handle;
 
         void* clientBufData;
@@ -725,7 +856,7 @@
         std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         writeLayers(layers);
@@ -793,7 +924,7 @@
         std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
 
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
@@ -859,7 +990,7 @@
         ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(),
                                        {0, 0, getDisplayWidth(), getDisplayHeight()}, BLUE);
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(layers);
         ASSERT_TRUE(mReader.takeErrors().empty());
@@ -916,7 +1047,7 @@
         ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), redRect, RED);
 
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         writeLayers(layers);
@@ -1026,7 +1157,7 @@
         ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), dimmerRedRect, DIM_RED);
 
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         writeLayers(layers);
@@ -1162,7 +1293,7 @@
         setExpectedColors(expectedColors);
 
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(mLayers);
         ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1207,7 +1338,7 @@
         setExpectedColors(expectedColors);
 
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(mLayers);
         ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1247,7 +1378,7 @@
         setExpectedColors(expectedColors);
 
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(mLayers);
         ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1321,7 +1452,7 @@
             return;
         }
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         mLayer->setTransform(Transform::FLIP_H);
         mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
@@ -1366,7 +1497,7 @@
             return;
         }
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         mLayer->setTransform(Transform::FLIP_V);
@@ -1411,7 +1542,7 @@
             return;
         }
         ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
-                                      getDisplayHeight(), mPixelFormat, mDataspace);
+                                      getDisplayHeight(), mPixelFormat);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         mLayer->setTransform(Transform::ROT_180);
diff --git a/identity/aidl/Android.bp b/identity/aidl/Android.bp
index 2090473..6a25e62 100644
--- a/identity/aidl/Android.bp
+++ b/identity/aidl/Android.bp
@@ -18,7 +18,7 @@
         "android.hardware.security.rkp-V3",
     ],
     stability: "vintf",
-    frozen: true,
+    frozen: false,
     backend: {
         java: {
             platform_apis: true,
@@ -67,20 +67,20 @@
 cc_defaults {
     name: "identity_use_latest_hal_aidl_ndk_static",
     static_libs: [
-        "android.hardware.identity-V4-ndk",
+        "android.hardware.identity-V5-ndk",
     ],
 }
 
 cc_defaults {
     name: "identity_use_latest_hal_aidl_ndk_shared",
     shared_libs: [
-        "android.hardware.identity-V4-ndk",
+        "android.hardware.identity-V5-ndk",
     ],
 }
 
 cc_defaults {
     name: "identity_use_latest_hal_aidl_cpp_static",
     static_libs: [
-        "android.hardware.identity-V4-cpp",
+        "android.hardware.identity-V5-cpp",
     ],
 }
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
index 5065641..4f2fe0b 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
@@ -51,4 +51,5 @@
   byte[] deleteCredentialWithChallenge(in byte[] challenge);
   byte[] proveOwnership(in byte[] challenge);
   android.hardware.identity.IWritableIdentityCredential updateCredential();
+  @SuppressWarnings(value={"out-array"}) void finishRetrievalWithSignature(out byte[] mac, out byte[] deviceNameSpaces, out byte[] ecdsaSignature);
 }
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index 82b0a83..abdb00b 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
@@ -194,7 +194,8 @@
      * is permissible for this to be empty in which case the readerSignature parameter
      * must also be empty. If this is not the case, the call fails with STATUS_FAILED.
      *
-     * If the SessionTranscript CBOR is not empty, the X and Y coordinates of the public
+     * If mdoc session encryption is used (e.g. createEphemeralKeyPair() has been called)
+     * and the SessionTranscript CBOR is not empty, the X and Y coordinates of the public
      * part of the key-pair previously generated by createEphemeralKeyPair() must appear
      * somewhere in the bytes of the CBOR. Each of these coordinates must appear encoded
      * with the most significant bits first and use the exact amount of bits indicated by
@@ -239,8 +240,8 @@
      *   and remove the corresponding requests from the counts.
      */
     void startRetrieval(in SecureAccessControlProfile[] accessControlProfiles,
-        in HardwareAuthToken authToken, in byte[] itemsRequest, in byte[] signingKeyBlob,
-        in byte[] sessionTranscript, in byte[] readerSignature, in int[] requestCounts);
+            in HardwareAuthToken authToken, in byte[] itemsRequest, in byte[] signingKeyBlob,
+            in byte[] sessionTranscript, in byte[] readerSignature, in int[] requestCounts);
 
     /**
      * Starts retrieving an entry, subject to access control requirements.  Entries must be
@@ -271,8 +272,8 @@
      *     is given and this profile wasn't passed to startRetrieval() this call fails
      *     with STATUS_INVALID_DATA.
      */
-    void startRetrieveEntryValue(in @utf8InCpp String nameSpace, in @utf8InCpp String name,
-                                 in int entrySize, in int[] accessControlProfileIds);
+    void startRetrieveEntryValue(in @utf8InCpp String nameSpace,
+            in @utf8InCpp String name, in int entrySize, in int[] accessControlProfileIds);
 
     /**
      * Retrieves an entry value, or part of one, if the entry value is larger than gcmChunkSize.
@@ -293,11 +294,13 @@
      * returned data.
      *
      * If signingKeyBlob or the sessionTranscript parameter passed to startRetrieval() is
-     * empty then the returned MAC will be empty.
+     * empty or if mdoc session encryption is not being used (e.g. if createEphemeralKeyPair()
+     * was not called) then the returned MAC will be empty.
      *
-     * @param out mac is empty if signingKeyBlob or the sessionTranscript passed to
-     *    startRetrieval() is empty. Otherwise it is a COSE_Mac0 with empty payload
-     *    and the detached content is set to DeviceAuthenticationBytes as defined below.
+     * @param out mac is empty if signingKeyBlob, or the sessionTranscript passed to
+     *    startRetrieval() is empty, or if mdoc session encryption is not being used (e.g. if
+     *    createEphemeralKeyPair() was not called). Otherwise it is a COSE_Mac0 with empty
+     *    payload and the detached content is set to DeviceAuthenticationBytes as defined below.
      *    This code is produced by using the key agreement and key derivation function
      *    from the ciphersuite with the authentication private key and the reader
      *    ephemeral public key to compute a shared message authentication code (MAC)
@@ -407,13 +410,13 @@
      */
     void setRequestedNamespaces(in RequestNamespace[] requestNamespaces);
 
-   /**
-    * Sets the VerificationToken. This method must be called before startRetrieval() is
-    * called. This token uses the same challenge as returned by createAuthChallenge().
-    *
-    * @param verificationToken
-    *   The verification token. This token is only valid if the timestamp field is non-zero.
-    */
+    /**
+     * Sets the VerificationToken. This method must be called before startRetrieval() is
+     * called. This token uses the same challenge as returned by createAuthChallenge().
+     *
+     * @param verificationToken
+     *   The verification token. This token is only valid if the timestamp field is non-zero.
+     */
     void setVerificationToken(in VerificationToken verificationToken);
 
     /**
@@ -485,4 +488,20 @@
      * @return an IWritableIdentityCredential
      */
     IWritableIdentityCredential updateCredential();
+
+    /**
+     * Like finishRetrieval() but also returns an ECDSA signature in addition to the MAC.
+     *
+     * See section 9.1.3.6 of ISO/IEC 18013-5:2021 for details of how the signature is calculated.
+     *
+     * Unlike MACing, an ECDSA signature will be returned even if mdoc session encryption isn't
+     * being used.
+     *
+     * This method was introduced in API version 5.
+     *
+     * @param ecdsaSignature a COSE_Sign1 signature described above.
+     */
+    @SuppressWarnings(value={"out-array"})
+    void finishRetrievalWithSignature(
+            out byte[] mac, out byte[] deviceNameSpaces, out byte[] ecdsaSignature);
 }
diff --git a/identity/aidl/android/hardware/identity/IPresentationSession.aidl b/identity/aidl/android/hardware/identity/IPresentationSession.aidl
index b0449f0..0a06740 100644
--- a/identity/aidl/android/hardware/identity/IPresentationSession.aidl
+++ b/identity/aidl/android/hardware/identity/IPresentationSession.aidl
@@ -70,6 +70,17 @@
      *
      * This can be empty but if it's non-empty it must be valid CBOR.
      *
+     * If mdoc session encryption is used (e.g. getEphemeralKeyPair() has been called)
+     * and the SessionTranscript CBOR is not empty, the X and Y coordinates of the public
+     * part of the key-pair previously generated by createEphemeralKeyPair() must appear
+     * somewhere in the bytes of the CBOR. Each of these coordinates must appear encoded
+     * with the most significant bits first and use the exact amount of bits indicated by
+     * the key size of the ephemeral keys. For example, if the ephemeral key is using the
+     * P-256 curve then the 32 bytes for the X coordinate encoded with the most significant
+     * bits first must appear somewhere in the CBOR and ditto for the 32 bytes for the Y
+     * coordinate. If this is not satisfied, the call fails with
+     * STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND.
+     *
      * This method may only be called once per instance. If called more than once, STATUS_FAILED
      * must be returned.
      *
diff --git a/identity/aidl/default/FakeSecureHardwareProxy.cpp b/identity/aidl/default/FakeSecureHardwareProxy.cpp
index 9b9a749..8551ab7 100644
--- a/identity/aidl/default/FakeSecureHardwareProxy.cpp
+++ b/identity/aidl/default/FakeSecureHardwareProxy.cpp
@@ -596,10 +596,10 @@
     return eicPresentationStartRetrieveEntries(&ctx_);
 }
 
-bool FakeSecureHardwarePresentationProxy::calcMacKey(
+bool FakeSecureHardwarePresentationProxy::prepareDeviceAuthentication(
         const vector<uint8_t>& sessionTranscript, const vector<uint8_t>& readerEphemeralPublicKey,
         const vector<uint8_t>& signingKeyBlob, const string& docType,
-        unsigned int numNamespacesWithValues, size_t expectedProofOfProvisioningSize) {
+        unsigned int numNamespacesWithValues, size_t expectedDeviceNamespacesSize) {
     if (!validateId(__func__)) {
         return false;
     }
@@ -608,10 +608,10 @@
         eicDebug("Unexpected size %zd of signingKeyBlob, expected 60", signingKeyBlob.size());
         return false;
     }
-    return eicPresentationCalcMacKey(&ctx_, sessionTranscript.data(), sessionTranscript.size(),
-                                     readerEphemeralPublicKey.data(), signingKeyBlob.data(),
-                                     docType.c_str(), docType.size(), numNamespacesWithValues,
-                                     expectedProofOfProvisioningSize);
+    return eicPresentationPrepareDeviceAuthentication(
+            &ctx_, sessionTranscript.data(), sessionTranscript.size(),
+            readerEphemeralPublicKey.data(), readerEphemeralPublicKey.size(), signingKeyBlob.data(),
+            docType.c_str(), docType.size(), numNamespacesWithValues, expectedDeviceNamespacesSize);
 }
 
 AccessCheckResult FakeSecureHardwarePresentationProxy::startRetrieveEntryValue(
@@ -673,6 +673,25 @@
     return content;
 }
 
+optional<pair<vector<uint8_t>, vector<uint8_t>>>
+FakeSecureHardwarePresentationProxy::finishRetrievalWithSignature() {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
+    vector<uint8_t> mac(32);
+    size_t macSize = 32;
+    vector<uint8_t> ecdsaSignature(EIC_ECDSA_P256_SIGNATURE_SIZE);
+    size_t ecdsaSignatureSize = EIC_ECDSA_P256_SIGNATURE_SIZE;
+    if (!eicPresentationFinishRetrievalWithSignature(&ctx_, mac.data(), &macSize,
+                                                     ecdsaSignature.data(), &ecdsaSignatureSize)) {
+        return std::nullopt;
+    }
+    mac.resize(macSize);
+    ecdsaSignature.resize(ecdsaSignatureSize);
+    return std::make_pair(mac, ecdsaSignature);
+}
+
 optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::finishRetrieval() {
     if (!validateId(__func__)) {
         return std::nullopt;
diff --git a/identity/aidl/default/FakeSecureHardwareProxy.h b/identity/aidl/default/FakeSecureHardwareProxy.h
index 2512074..b56ab93 100644
--- a/identity/aidl/default/FakeSecureHardwareProxy.h
+++ b/identity/aidl/default/FakeSecureHardwareProxy.h
@@ -175,11 +175,11 @@
                                 const vector<uint8_t>& requestMessage, int coseSignAlg,
                                 const vector<uint8_t>& readerSignatureOfToBeSigned) override;
 
-    bool calcMacKey(const vector<uint8_t>& sessionTranscript,
-                    const vector<uint8_t>& readerEphemeralPublicKey,
-                    const vector<uint8_t>& signingKeyBlob, const string& docType,
-                    unsigned int numNamespacesWithValues,
-                    size_t expectedProofOfProvisioningSize) override;
+    bool prepareDeviceAuthentication(const vector<uint8_t>& sessionTranscript,
+                                     const vector<uint8_t>& readerEphemeralPublicKey,
+                                     const vector<uint8_t>& signingKeyBlob, const string& docType,
+                                     unsigned int numNamespacesWithValues,
+                                     size_t expectedDeviceNamespacesSize) override;
 
     AccessCheckResult startRetrieveEntryValue(
             const string& nameSpace, const string& name, unsigned int newNamespaceNumEntries,
@@ -191,6 +191,8 @@
 
     optional<vector<uint8_t>> finishRetrieval() override;
 
+    optional<pair<vector<uint8_t>, vector<uint8_t>>> finishRetrievalWithSignature() override;
+
     optional<vector<uint8_t>> deleteCredential(const string& docType,
                                                const vector<uint8_t>& challenge,
                                                bool includeChallenge,
diff --git a/identity/aidl/default/common/IdentityCredential.cpp b/identity/aidl/default/common/IdentityCredential.cpp
index ff80752..4c3b7b2 100644
--- a/identity/aidl/default/common/IdentityCredential.cpp
+++ b/identity/aidl/default/common/IdentityCredential.cpp
@@ -457,17 +457,16 @@
     }
 
     if (session_) {
-        // If presenting in a session, the TA has already done this check.
-
+        // If presenting in a session, the TA has already done the check for (X, Y) as done
+        // below, see eicSessionSetSessionTranscript().
     } else {
-        // To prevent replay-attacks, we check that the public part of the ephemeral
-        // key we previously created, is present in the DeviceEngagement part of
-        // SessionTranscript as a COSE_Key, in uncompressed form.
+        // If mdoc session encryption is in use, check that the
+        // public part of the ephemeral key we previously created, is
+        // present in the DeviceEngagement part of SessionTranscript
+        // as a COSE_Key, in uncompressed form.
         //
         // We do this by just searching for the X and Y coordinates.
-        //
-        // Would be nice to move this check to the TA.
-        if (sessionTranscript.size() > 0) {
+        if (sessionTranscript.size() > 0 && ephemeralPublicKey_.size() > 0) {
             auto [getXYSuccess, ePubX, ePubY] = support::ecPublicKeyGetXandY(ephemeralPublicKey_);
             if (!getXYSuccess) {
                 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -608,33 +607,36 @@
     // Finally, pass info so the HMAC key can be derived and the TA can start
     // creating the DeviceNameSpaces CBOR...
     if (!session_) {
-        if (sessionTranscript_.size() > 0 && readerPublicKey_.size() > 0 &&
-            signingKeyBlob.size() > 0) {
-            // We expect the reader ephemeral public key to be same size and curve
-            // as the ephemeral key we generated (e.g. P-256 key), otherwise ECDH
-            // won't work. So its length should be 65 bytes and it should be
-            // starting with 0x04.
-            if (readerPublicKey_.size() != 65 || readerPublicKey_[0] != 0x04) {
-                return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                        IIdentityCredentialStore::STATUS_FAILED,
-                        "Reader public key is not in expected format"));
+        if (sessionTranscript_.size() > 0 && signingKeyBlob.size() > 0) {
+            vector<uint8_t> eReaderKeyP256;
+            if (readerPublicKey_.size() > 0) {
+                // If set, we expect the reader ephemeral public key to be same size and curve
+                // as the ephemeral key we generated (e.g. P-256 key), otherwise ECDH won't
+                // work. So its length should be 65 bytes and it should be starting with 0x04.
+                if (readerPublicKey_.size() != 65 || readerPublicKey_[0] != 0x04) {
+                    return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                            IIdentityCredentialStore::STATUS_FAILED,
+                            "Reader public key is not in expected format"));
+                }
+                eReaderKeyP256 =
+                        vector<uint8_t>(readerPublicKey_.begin() + 1, readerPublicKey_.end());
             }
-            vector<uint8_t> pubKeyP256(readerPublicKey_.begin() + 1, readerPublicKey_.end());
-            if (!hwProxy_->calcMacKey(sessionTranscript_, pubKeyP256, signingKeyBlob, docType_,
-                                      numNamespacesWithValues, expectedDeviceNameSpacesSize_)) {
+            if (!hwProxy_->prepareDeviceAuthentication(
+                        sessionTranscript_, eReaderKeyP256, signingKeyBlob, docType_,
+                        numNamespacesWithValues, expectedDeviceNameSpacesSize_)) {
                 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                         IIdentityCredentialStore::STATUS_FAILED,
                         "Error starting retrieving entries"));
             }
         }
     } else {
-        if (session_->getSessionTranscript().size() > 0 &&
-            session_->getReaderEphemeralPublicKey().size() > 0 && signingKeyBlob.size() > 0) {
+        if (session_->getSessionTranscript().size() > 0 && signingKeyBlob.size() > 0) {
             // Don't actually pass the reader ephemeral public key in, the TA will get
             // it from the session object.
             //
-            if (!hwProxy_->calcMacKey(sessionTranscript_, {}, signingKeyBlob, docType_,
-                                      numNamespacesWithValues, expectedDeviceNameSpacesSize_)) {
+            if (!hwProxy_->prepareDeviceAuthentication(sessionTranscript_, {}, signingKeyBlob,
+                                                       docType_, numNamespacesWithValues,
+                                                       expectedDeviceNameSpacesSize_)) {
                 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                         IIdentityCredentialStore::STATUS_FAILED,
                         "Error starting retrieving entries"));
@@ -924,8 +926,9 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<uint8_t>* outMac,
-                                                       vector<uint8_t>* outDeviceNameSpaces) {
+ndk::ScopedAStatus IdentityCredential::finishRetrievalWithSignature(
+        vector<uint8_t>* outMac, vector<uint8_t>* outDeviceNameSpaces,
+        vector<uint8_t>* outEcdsaSignature) {
     ndk::ScopedAStatus status = ensureHwProxy();
     if (!status.isOk()) {
         return status;
@@ -948,17 +951,34 @@
                         .c_str()));
     }
 
+    optional<vector<uint8_t>> digestToBeMaced;
+    optional<vector<uint8_t>> signatureToBeSigned;
+
+    // This relies on the fact that binder calls never pass a nullptr
+    // for out parameters. Hence if it's null here we know this was
+    // called from finishRetrieval() below.
+    if (outEcdsaSignature == nullptr) {
+        digestToBeMaced = hwProxy_->finishRetrieval();
+        if (!digestToBeMaced) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "Error generating digestToBeMaced"));
+        }
+    } else {
+        auto macAndSignature = hwProxy_->finishRetrievalWithSignature();
+        if (!macAndSignature) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "Error generating digestToBeMaced and signatureToBeSigned"));
+        }
+        digestToBeMaced = macAndSignature->first;
+        signatureToBeSigned = macAndSignature->second;
+    }
+
     // If the TA calculated a MAC (it might not have), format it as a COSE_Mac0
     //
-    optional<vector<uint8_t>> mac;
-    optional<vector<uint8_t>> digestToBeMaced = hwProxy_->finishRetrieval();
-
-    // The MAC not being set means an error occurred.
-    if (!digestToBeMaced) {
-        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                IIdentityCredentialStore::STATUS_INVALID_DATA, "Error generating digestToBeMaced"));
-    }
     // Size 0 means that the MAC isn't set. If it's set, it has to be 32 bytes.
+    optional<vector<uint8_t>> mac;
     if (digestToBeMaced.value().size() != 0) {
         if (digestToBeMaced.value().size() != 32) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -967,12 +987,27 @@
         }
         mac = support::coseMacWithDigest(digestToBeMaced.value(), {} /* data */);
     }
-
     *outMac = mac.value_or(vector<uint8_t>({}));
+
+    optional<vector<uint8_t>> signature;
+    if (signatureToBeSigned && signatureToBeSigned.value().size() != 0) {
+        signature = support::coseSignEcDsaWithSignature(signatureToBeSigned.value(), {},  // data
+                                                        {});  // certificateChain
+    }
+    if (outEcdsaSignature != nullptr) {
+        *outEcdsaSignature = signature.value_or(vector<uint8_t>({}));
+    }
+
     *outDeviceNameSpaces = encodedDeviceNameSpaces;
+
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<uint8_t>* outMac,
+                                                       vector<uint8_t>* outDeviceNameSpaces) {
+    return finishRetrievalWithSignature(outMac, outDeviceNameSpaces, nullptr);
+}
+
 ndk::ScopedAStatus IdentityCredential::generateSigningKeyPair(
         vector<uint8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) {
     if (session_) {
diff --git a/identity/aidl/default/common/IdentityCredential.h b/identity/aidl/default/common/IdentityCredential.h
index 5929829..1e0cd64 100644
--- a/identity/aidl/default/common/IdentityCredential.h
+++ b/identity/aidl/default/common/IdentityCredential.h
@@ -92,6 +92,10 @@
     ndk::ScopedAStatus updateCredential(
             shared_ptr<IWritableIdentityCredential>* outWritableCredential) override;
 
+    ndk::ScopedAStatus finishRetrievalWithSignature(vector<uint8_t>* outMac,
+                                                    vector<uint8_t>* outDeviceNameSpaces,
+                                                    vector<uint8_t>* outEcdsaSignature) override;
+
   private:
     ndk::ScopedAStatus deleteCredentialCommon(const vector<uint8_t>& challenge,
                                               bool includeChallenge,
diff --git a/identity/aidl/default/common/PresentationSession.cpp b/identity/aidl/default/common/PresentationSession.cpp
index 2eb7f2e..cf5b066 100644
--- a/identity/aidl/default/common/PresentationSession.cpp
+++ b/identity/aidl/default/common/PresentationSession.cpp
@@ -54,19 +54,6 @@
     }
     id_ = id.value();
 
-    optional<vector<uint8_t>> ephemeralKeyPriv = hwProxy_->getEphemeralKeyPair();
-    if (!ephemeralKeyPriv) {
-        LOG(ERROR) << "Error getting ephemeral private key for session";
-        return IIdentityCredentialStore::STATUS_FAILED;
-    }
-    optional<vector<uint8_t>> ephemeralKeyPair =
-            support::ecPrivateKeyToKeyPair(ephemeralKeyPriv.value());
-    if (!ephemeralKeyPair) {
-        LOG(ERROR) << "Error creating ephemeral key-pair";
-        return IIdentityCredentialStore::STATUS_FAILED;
-    }
-    ephemeralKeyPair_ = ephemeralKeyPair.value();
-
     optional<uint64_t> authChallenge = hwProxy_->getAuthChallenge();
     if (!authChallenge) {
         LOG(ERROR) << "Error getting authChallenge for session";
@@ -78,6 +65,23 @@
 }
 
 ndk::ScopedAStatus PresentationSession::getEphemeralKeyPair(vector<uint8_t>* outKeyPair) {
+    if (ephemeralKeyPair_.size() == 0) {
+        optional<vector<uint8_t>> ephemeralKeyPriv = hwProxy_->getEphemeralKeyPair();
+        if (!ephemeralKeyPriv) {
+            LOG(ERROR) << "Error getting ephemeral private key for session";
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_FAILED,
+                    "Error getting ephemeral private key for session"));
+        }
+        optional<vector<uint8_t>> ephemeralKeyPair =
+                support::ecPrivateKeyToKeyPair(ephemeralKeyPriv.value());
+        if (!ephemeralKeyPair) {
+            LOG(ERROR) << "Error creating ephemeral key-pair";
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_FAILED, "Error creating ephemeral key-pair"));
+        }
+        ephemeralKeyPair_ = ephemeralKeyPair.value();
+    }
     *outKeyPair = ephemeralKeyPair_;
     return ndk::ScopedAStatus::ok();
 }
diff --git a/identity/aidl/default/common/PresentationSession.h b/identity/aidl/default/common/PresentationSession.h
index 4cb174a..b3d46f9 100644
--- a/identity/aidl/default/common/PresentationSession.h
+++ b/identity/aidl/default/common/PresentationSession.h
@@ -72,9 +72,11 @@
 
     // Set by initialize()
     uint64_t id_;
-    vector<uint8_t> ephemeralKeyPair_;
     uint64_t authChallenge_;
 
+    // Set by getEphemeralKeyPair()
+    vector<uint8_t> ephemeralKeyPair_;
+
     // Set by setReaderEphemeralPublicKey()
     vector<uint8_t> readerPublicKey_;
 
diff --git a/identity/aidl/default/common/SecureHardwareProxy.h b/identity/aidl/default/common/SecureHardwareProxy.h
index 9f63ad8..6463318 100644
--- a/identity/aidl/default/common/SecureHardwareProxy.h
+++ b/identity/aidl/default/common/SecureHardwareProxy.h
@@ -194,11 +194,12 @@
                                         const vector<uint8_t>& requestMessage, int coseSignAlg,
                                         const vector<uint8_t>& readerSignatureOfToBeSigned) = 0;
 
-    virtual bool calcMacKey(const vector<uint8_t>& sessionTranscript,
-                            const vector<uint8_t>& readerEphemeralPublicKey,
-                            const vector<uint8_t>& signingKeyBlob, const string& docType,
-                            unsigned int numNamespacesWithValues,
-                            size_t expectedProofOfProvisioningSize) = 0;
+    virtual bool prepareDeviceAuthentication(const vector<uint8_t>& sessionTranscript,
+                                             const vector<uint8_t>& readerEphemeralPublicKey,
+                                             const vector<uint8_t>& signingKeyBlob,
+                                             const string& docType,
+                                             unsigned int numNamespacesWithValues,
+                                             size_t expectedDeviceNamespacesSize) = 0;
 
     virtual AccessCheckResult startRetrieveEntryValue(
             const string& nameSpace, const string& name, unsigned int newNamespaceNumEntries,
@@ -209,6 +210,7 @@
             const vector<int32_t>& accessControlProfileIds) = 0;
 
     virtual optional<vector<uint8_t>> finishRetrieval();
+    virtual optional<pair<vector<uint8_t>, vector<uint8_t>>> finishRetrievalWithSignature();
 
     virtual optional<vector<uint8_t>> deleteCredential(const string& docType,
                                                        const vector<uint8_t>& challenge,
diff --git a/identity/aidl/default/identity-default.xml b/identity/aidl/default/identity-default.xml
index cc0ddc7..d0d43af 100644
--- a/identity/aidl/default/identity-default.xml
+++ b/identity/aidl/default/identity-default.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.identity</name>
-        <version>4</version>
+        <version>5</version>
         <interface>
             <name>IIdentityCredentialStore</name>
             <instance>default</instance>
diff --git a/identity/aidl/default/libeic/EicPresentation.c b/identity/aidl/default/libeic/EicPresentation.c
index 104a559..23fd0b3 100644
--- a/identity/aidl/default/libeic/EicPresentation.c
+++ b/identity/aidl/default/libeic/EicPresentation.c
@@ -557,87 +557,11 @@
     return true;
 }
 
-bool eicPresentationCalcMacKey(EicPresentation* ctx, const uint8_t* sessionTranscript,
-                               size_t sessionTranscriptSize,
-                               const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE],
-                               const uint8_t signingKeyBlob[60], const char* docType,
-                               size_t docTypeLength, unsigned int numNamespacesWithValues,
-                               size_t expectedDeviceNamespacesSize) {
-    if (ctx->sessionId != 0) {
-        EicSession* session = eicSessionGetForId(ctx->sessionId);
-        if (session == NULL) {
-            eicDebug("Error looking up session for sessionId %" PRIu32, ctx->sessionId);
-            return false;
-        }
-        EicSha256Ctx sha256;
-        uint8_t sessionTranscriptSha256[EIC_SHA256_DIGEST_SIZE];
-        eicOpsSha256Init(&sha256);
-        eicOpsSha256Update(&sha256, sessionTranscript, sessionTranscriptSize);
-        eicOpsSha256Final(&sha256, sessionTranscriptSha256);
-        if (eicCryptoMemCmp(sessionTranscriptSha256, session->sessionTranscriptSha256,
-                            EIC_SHA256_DIGEST_SIZE) != 0) {
-            eicDebug("SessionTranscript mismatch");
-            return false;
-        }
-        readerEphemeralPublicKey = session->readerEphemeralPublicKey;
-    }
-
-    uint8_t signingKeyPriv[EIC_P256_PRIV_KEY_SIZE];
-    if (!eicOpsDecryptAes128Gcm(ctx->storageKey, signingKeyBlob, 60, (const uint8_t*)docType,
-                                docTypeLength, signingKeyPriv)) {
-        eicDebug("Error decrypting signingKeyBlob");
-        return false;
-    }
-
-    uint8_t sharedSecret[EIC_P256_COORDINATE_SIZE];
-    if (!eicOpsEcdh(readerEphemeralPublicKey, signingKeyPriv, sharedSecret)) {
-        eicDebug("ECDH failed");
-        return false;
-    }
-
-    EicCbor cbor;
-    eicCborInit(&cbor, NULL, 0);
-    eicCborAppendSemantic(&cbor, EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR);
-    eicCborAppendByteString(&cbor, sessionTranscript, sessionTranscriptSize);
-    uint8_t salt[EIC_SHA256_DIGEST_SIZE];
-    eicCborFinal(&cbor, salt);
-
-    const uint8_t info[7] = {'E', 'M', 'a', 'c', 'K', 'e', 'y'};
-    uint8_t derivedKey[32];
-    if (!eicOpsHkdf(sharedSecret, EIC_P256_COORDINATE_SIZE, salt, sizeof(salt), info, sizeof(info),
-                    derivedKey, sizeof(derivedKey))) {
-        eicDebug("HKDF failed");
-        return false;
-    }
-
-    eicCborInitHmacSha256(&ctx->cbor, NULL, 0, derivedKey, sizeof(derivedKey));
-    ctx->buildCbor = true;
-
-    // What we're going to calculate the HMAC-SHA256 is the COSE ToBeMaced
-    // structure which looks like the following:
-    //
-    // MAC_structure = [
-    //   context : "MAC" / "MAC0",
-    //   protected : empty_or_serialized_map,
-    //   external_aad : bstr,
-    //   payload : bstr
-    // ]
-    //
-    eicCborAppendArray(&ctx->cbor, 4);
-    eicCborAppendStringZ(&ctx->cbor, "MAC0");
-
-    // The COSE Encoded protected headers is just a single field with
-    // COSE_LABEL_ALG (1) -> COSE_ALG_HMAC_256_256 (5). For simplicitly we just
-    // hard-code the CBOR encoding:
-    static const uint8_t coseEncodedProtectedHeaders[] = {0xa1, 0x01, 0x05};
-    eicCborAppendByteString(&ctx->cbor, coseEncodedProtectedHeaders,
-                            sizeof(coseEncodedProtectedHeaders));
-
-    // We currently don't support Externally Supplied Data (RFC 8152 section 4.3)
-    // so external_aad is the empty bstr
-    static const uint8_t externalAad[0] = {};
-    eicCborAppendByteString(&ctx->cbor, externalAad, sizeof(externalAad));
-
+// Helper used to append the DeviceAuthencation prelude, used for both MACing and ECDSA signing.
+static size_t appendDeviceAuthentication(EicCbor* cbor, const uint8_t* sessionTranscript,
+                                         size_t sessionTranscriptSize, const char* docType,
+                                         size_t docTypeLength,
+                                         size_t expectedDeviceNamespacesSize) {
     // For the payload, the _encoded_ form follows here. We handle this by simply
     // opening a bstr, and then writing the CBOR. This requires us to know the
     // size of said bstr, ahead of time... the CBOR to be written is
@@ -674,26 +598,148 @@
     dabCalculatedSize += calculatedSize;
 
     // Begin the bytestring for DeviceAuthenticationBytes;
-    eicCborBegin(&ctx->cbor, EIC_CBOR_MAJOR_TYPE_BYTE_STRING, dabCalculatedSize);
+    eicCborBegin(cbor, EIC_CBOR_MAJOR_TYPE_BYTE_STRING, dabCalculatedSize);
 
-    eicCborAppendSemantic(&ctx->cbor, EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR);
+    eicCborAppendSemantic(cbor, EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR);
 
     // Begins the bytestring for DeviceAuthentication;
-    eicCborBegin(&ctx->cbor, EIC_CBOR_MAJOR_TYPE_BYTE_STRING, calculatedSize);
+    eicCborBegin(cbor, EIC_CBOR_MAJOR_TYPE_BYTE_STRING, calculatedSize);
 
-    eicCborAppendArray(&ctx->cbor, 4);
-    eicCborAppendStringZ(&ctx->cbor, "DeviceAuthentication");
-    eicCborAppend(&ctx->cbor, sessionTranscript, sessionTranscriptSize);
-    eicCborAppendString(&ctx->cbor, docType, docTypeLength);
+    eicCborAppendArray(cbor, 4);
+    eicCborAppendStringZ(cbor, "DeviceAuthentication");
+    eicCborAppend(cbor, sessionTranscript, sessionTranscriptSize);
+    eicCborAppendString(cbor, docType, docTypeLength);
 
     // For the payload, the _encoded_ form follows here. We handle this by simply
     // opening a bstr, and then writing the CBOR. This requires us to know the
     // size of said bstr, ahead of time.
-    eicCborAppendSemantic(&ctx->cbor, EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR);
-    eicCborBegin(&ctx->cbor, EIC_CBOR_MAJOR_TYPE_BYTE_STRING, expectedDeviceNamespacesSize);
-    ctx->expectedCborSizeAtEnd = expectedDeviceNamespacesSize + ctx->cbor.size;
+    eicCborAppendSemantic(cbor, EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR);
+    eicCborBegin(cbor, EIC_CBOR_MAJOR_TYPE_BYTE_STRING, expectedDeviceNamespacesSize);
+    size_t expectedCborSizeAtEnd = expectedDeviceNamespacesSize + cbor->size;
 
-    eicCborAppendMap(&ctx->cbor, numNamespacesWithValues);
+    return expectedCborSizeAtEnd;
+}
+
+bool eicPresentationPrepareDeviceAuthentication(
+        EicPresentation* ctx, const uint8_t* sessionTranscript, size_t sessionTranscriptSize,
+        const uint8_t* readerEphemeralPublicKey, size_t readerEphemeralPublicKeySize,
+        const uint8_t signingKeyBlob[60], const char* docType, size_t docTypeLength,
+        unsigned int numNamespacesWithValues, size_t expectedDeviceNamespacesSize) {
+    if (ctx->sessionId != 0) {
+        if (readerEphemeralPublicKeySize != 0) {
+            eicDebug("In a session but readerEphemeralPublicKeySize is non-zero");
+            return false;
+        }
+        EicSession* session = eicSessionGetForId(ctx->sessionId);
+        if (session == NULL) {
+            eicDebug("Error looking up session for sessionId %" PRIu32, ctx->sessionId);
+            return false;
+        }
+        EicSha256Ctx sha256;
+        uint8_t sessionTranscriptSha256[EIC_SHA256_DIGEST_SIZE];
+        eicOpsSha256Init(&sha256);
+        eicOpsSha256Update(&sha256, sessionTranscript, sessionTranscriptSize);
+        eicOpsSha256Final(&sha256, sessionTranscriptSha256);
+        if (eicCryptoMemCmp(sessionTranscriptSha256, session->sessionTranscriptSha256,
+                            EIC_SHA256_DIGEST_SIZE) != 0) {
+            eicDebug("SessionTranscript mismatch");
+            return false;
+        }
+        readerEphemeralPublicKey = session->readerEphemeralPublicKey;
+        readerEphemeralPublicKeySize = session->readerEphemeralPublicKeySize;
+    }
+
+    // Stash the decrypted DeviceKey in context since we'll need it later in
+    // eicPresentationFinishRetrievalWithSignature()
+    if (!eicOpsDecryptAes128Gcm(ctx->storageKey, signingKeyBlob, 60, (const uint8_t*)docType,
+                                docTypeLength, ctx->deviceKeyPriv)) {
+        eicDebug("Error decrypting signingKeyBlob");
+        return false;
+    }
+
+    // We can only do MACing if EReaderKey has been set... it might not have been set if for
+    // example mdoc session encryption isn't in use. In that case we can still do ECDSA
+    if (readerEphemeralPublicKeySize > 0) {
+        if (readerEphemeralPublicKeySize != EIC_P256_PUB_KEY_SIZE) {
+            eicDebug("Unexpected size %zd for readerEphemeralPublicKeySize",
+                     readerEphemeralPublicKeySize);
+            return false;
+        }
+
+        uint8_t sharedSecret[EIC_P256_COORDINATE_SIZE];
+        if (!eicOpsEcdh(readerEphemeralPublicKey, ctx->deviceKeyPriv, sharedSecret)) {
+            eicDebug("ECDH failed");
+            return false;
+        }
+
+        EicCbor cbor;
+        eicCborInit(&cbor, NULL, 0);
+        eicCborAppendSemantic(&cbor, EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR);
+        eicCborAppendByteString(&cbor, sessionTranscript, sessionTranscriptSize);
+        uint8_t salt[EIC_SHA256_DIGEST_SIZE];
+        eicCborFinal(&cbor, salt);
+
+        const uint8_t info[7] = {'E', 'M', 'a', 'c', 'K', 'e', 'y'};
+        uint8_t derivedKey[32];
+        if (!eicOpsHkdf(sharedSecret, EIC_P256_COORDINATE_SIZE, salt, sizeof(salt), info,
+                        sizeof(info), derivedKey, sizeof(derivedKey))) {
+            eicDebug("HKDF failed");
+            return false;
+        }
+
+        eicCborInitHmacSha256(&ctx->cbor, NULL, 0, derivedKey, sizeof(derivedKey));
+
+        // What we're going to calculate the HMAC-SHA256 is the COSE ToBeMaced
+        // structure which looks like the following:
+        //
+        // MAC_structure = [
+        //   context : "MAC" / "MAC0",
+        //   protected : empty_or_serialized_map,
+        //   external_aad : bstr,
+        //   payload : bstr
+        // ]
+        //
+        eicCborAppendArray(&ctx->cbor, 4);
+        eicCborAppendStringZ(&ctx->cbor, "MAC0");
+
+        // The COSE Encoded protected headers is just a single field with
+        // COSE_LABEL_ALG (1) -> COSE_ALG_HMAC_256_256 (5). For simplicitly we just
+        // hard-code the CBOR encoding:
+        static const uint8_t coseEncodedProtectedHeaders[] = {0xa1, 0x01, 0x05};
+        eicCborAppendByteString(&ctx->cbor, coseEncodedProtectedHeaders,
+                                sizeof(coseEncodedProtectedHeaders));
+
+        // We currently don't support Externally Supplied Data (RFC 8152 section 4.3)
+        // so external_aad is the empty bstr
+        static const uint8_t externalAad[0] = {};
+        eicCborAppendByteString(&ctx->cbor, externalAad, sizeof(externalAad));
+
+        // Append DeviceAuthentication prelude and open the DeviceSigned map...
+        ctx->expectedCborSizeAtEnd =
+                appendDeviceAuthentication(&ctx->cbor, sessionTranscript, sessionTranscriptSize,
+                                           docType, docTypeLength, expectedDeviceNamespacesSize);
+        eicCborAppendMap(&ctx->cbor, numNamespacesWithValues);
+        ctx->buildCbor = true;
+    }
+
+    // Now do the same for ECDSA signatures...
+    //
+    eicCborInit(&ctx->cborEcdsa, NULL, 0);
+    eicCborAppendArray(&ctx->cborEcdsa, 4);
+    eicCborAppendStringZ(&ctx->cborEcdsa, "Signature1");
+    static const uint8_t coseEncodedProtectedHeadersEcdsa[] = {0xa1, 0x01, 0x26};
+    eicCborAppendByteString(&ctx->cborEcdsa, coseEncodedProtectedHeadersEcdsa,
+                            sizeof(coseEncodedProtectedHeadersEcdsa));
+    static const uint8_t externalAadEcdsa[0] = {};
+    eicCborAppendByteString(&ctx->cborEcdsa, externalAadEcdsa, sizeof(externalAadEcdsa));
+
+    // Append DeviceAuthentication prelude and open the DeviceSigned map...
+    ctx->expectedCborEcdsaSizeAtEnd =
+            appendDeviceAuthentication(&ctx->cborEcdsa, sessionTranscript, sessionTranscriptSize,
+                                       docType, docTypeLength, expectedDeviceNamespacesSize);
+    eicCborAppendMap(&ctx->cborEcdsa, numNamespacesWithValues);
+    ctx->buildCborEcdsa = true;
+
     return true;
 }
 
@@ -702,6 +748,7 @@
     // state objects here.
     ctx->requestMessageValidated = false;
     ctx->buildCbor = false;
+    ctx->buildCborEcdsa = false;
     ctx->accessControlProfileMaskValidated = 0;
     ctx->accessControlProfileMaskUsesReaderAuth = 0;
     ctx->accessControlProfileMaskFailedReaderAuth = 0;
@@ -724,6 +771,9 @@
     if (newNamespaceNumEntries > 0) {
         eicCborAppendString(&ctx->cbor, nameSpace, nameSpaceLength);
         eicCborAppendMap(&ctx->cbor, newNamespaceNumEntries);
+
+        eicCborAppendString(&ctx->cborEcdsa, nameSpace, nameSpaceLength);
+        eicCborAppendMap(&ctx->cborEcdsa, newNamespaceNumEntries);
     }
 
     // We'll need to calc and store a digest of additionalData to check that it's the same
@@ -778,6 +828,7 @@
 
     if (result == EIC_ACCESS_CHECK_RESULT_OK) {
         eicCborAppendString(&ctx->cbor, name, nameLength);
+        eicCborAppendString(&ctx->cborEcdsa, name, nameLength);
         ctx->accessCheckOk = true;
     }
     return result;
@@ -821,6 +872,7 @@
     }
 
     eicCborAppend(&ctx->cbor, content, encryptedContentSize - 28);
+    eicCborAppend(&ctx->cborEcdsa, content, encryptedContentSize - 28);
 
     return true;
 }
@@ -842,6 +894,40 @@
         return false;
     }
     eicCborFinal(&ctx->cbor, digestToBeMaced);
+
+    return true;
+}
+
+bool eicPresentationFinishRetrievalWithSignature(EicPresentation* ctx, uint8_t* digestToBeMaced,
+                                                 size_t* digestToBeMacedSize,
+                                                 uint8_t* signatureOfToBeSigned,
+                                                 size_t* signatureOfToBeSignedSize) {
+    if (!eicPresentationFinishRetrieval(ctx, digestToBeMaced, digestToBeMacedSize)) {
+        return false;
+    }
+
+    if (!ctx->buildCborEcdsa) {
+        *signatureOfToBeSignedSize = 0;
+        return true;
+    }
+    if (*signatureOfToBeSignedSize != EIC_ECDSA_P256_SIGNATURE_SIZE) {
+        return false;
+    }
+
+    // This verifies that the correct expectedDeviceNamespacesSize value was
+    // passed in at eicPresentationCalcMacKey() time.
+    if (ctx->cborEcdsa.size != ctx->expectedCborEcdsaSizeAtEnd) {
+        eicDebug("CBOR ECDSA size is %zd, was expecting %zd", ctx->cborEcdsa.size,
+                 ctx->expectedCborEcdsaSizeAtEnd);
+        return false;
+    }
+    uint8_t cborSha256[EIC_SHA256_DIGEST_SIZE];
+    eicCborFinal(&ctx->cborEcdsa, cborSha256);
+    if (!eicOpsEcDsa(ctx->deviceKeyPriv, cborSha256, signatureOfToBeSigned)) {
+        eicDebug("Error signing DeviceAuthentication");
+        return false;
+    }
+    eicDebug("set the signature");
     return true;
 }
 
diff --git a/identity/aidl/default/libeic/EicPresentation.h b/identity/aidl/default/libeic/EicPresentation.h
index a031890..cd3162a 100644
--- a/identity/aidl/default/libeic/EicPresentation.h
+++ b/identity/aidl/default/libeic/EicPresentation.h
@@ -76,6 +76,7 @@
     // aren't.
     bool requestMessageValidated;
     bool buildCbor;
+    bool buildCborEcdsa;
 
     // Set to true initialized as a test credential.
     bool testCredential;
@@ -101,6 +102,12 @@
 
     size_t expectedCborSizeAtEnd;
     EicCbor cbor;
+
+    // The selected DeviceKey / AuthKey
+    uint8_t deviceKeyPriv[EIC_P256_PRIV_KEY_SIZE];
+
+    EicCbor cborEcdsa;
+    size_t expectedCborEcdsaSizeAtEnd;
 } EicPresentation;
 
 // If sessionId is zero (EIC_PRESENTATION_ID_UNSET), the presentation object is not associated
@@ -214,14 +221,13 @@
     EIC_ACCESS_CHECK_RESULT_READER_AUTHENTICATION_FAILED,
 } EicAccessCheckResult;
 
-// Passes enough information to calculate the MACing key
+// Passes enough information to calculate the MACing key and/or prepare ECDSA signing
 //
-bool eicPresentationCalcMacKey(EicPresentation* ctx, const uint8_t* sessionTranscript,
-                               size_t sessionTranscriptSize,
-                               const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE],
-                               const uint8_t signingKeyBlob[60], const char* docType,
-                               size_t docTypeLength, unsigned int numNamespacesWithValues,
-                               size_t expectedDeviceNamespacesSize);
+bool eicPresentationPrepareDeviceAuthentication(
+        EicPresentation* ctx, const uint8_t* sessionTranscript, size_t sessionTranscriptSize,
+        const uint8_t* readerEphemeralPublicKey, size_t readerEphemeralPublicKeySize,
+        const uint8_t signingKeyBlob[60], const char* docType, size_t docTypeLength,
+        unsigned int numNamespacesWithValues, size_t expectedDeviceNamespacesSize);
 
 // The scratchSpace should be set to a buffer at least 512 bytes (ideally 1024
 // bytes, the bigger the better). It's done this way to avoid allocating stack
@@ -253,6 +259,13 @@
 bool eicPresentationFinishRetrieval(EicPresentation* ctx, uint8_t* digestToBeMaced,
                                     size_t* digestToBeMacedSize);
 
+// Like eicPresentationFinishRetrieval() but also returns an ECDSA signature.
+//
+bool eicPresentationFinishRetrievalWithSignature(EicPresentation* ctx, uint8_t* digestToBeMaced,
+                                                 size_t* digestToBeMacedSize,
+                                                 uint8_t* signatureOfToBeSigned,
+                                                 size_t* signatureOfToBeSignedSize);
+
 // The data returned in |signatureOfToBeSigned| contains the ECDSA signature of
 // the ToBeSigned CBOR from RFC 8051 "4.4. Signing and Verification Process"
 // where content is set to the ProofOfDeletion CBOR.
diff --git a/identity/aidl/default/libeic/EicSession.c b/identity/aidl/default/libeic/EicSession.c
index d0c7a0d..e44fa68 100644
--- a/identity/aidl/default/libeic/EicSession.c
+++ b/identity/aidl/default/libeic/EicSession.c
@@ -84,30 +84,35 @@
 bool eicSessionGetEphemeralKeyPair(EicSession* ctx,
                                    uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE]) {
     eicMemCpy(ephemeralPrivateKey, ctx->ephemeralPrivateKey, EIC_P256_PRIV_KEY_SIZE);
+    ctx->getEphemeralKeyPairCalled = true;
     return true;
 }
 
 bool eicSessionSetReaderEphemeralPublicKey(
         EicSession* ctx, const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE]) {
     eicMemCpy(ctx->readerEphemeralPublicKey, readerEphemeralPublicKey, EIC_P256_PUB_KEY_SIZE);
+    ctx->readerEphemeralPublicKeySize = EIC_P256_PUB_KEY_SIZE;
     return true;
 }
 
 bool eicSessionSetSessionTranscript(EicSession* ctx, const uint8_t* sessionTranscript,
                                     size_t sessionTranscriptSize) {
-    // Only accept the SessionTranscript if X and Y from the ephemeral key
-    // we created is somewhere in SessionTranscript...
+    // If mdoc session encryption is in use, only accept the
+    // SessionTranscript if X and Y from the ephemeral key we created
+    // is somewhere in SessionTranscript...
     //
-    if (eicMemMem(sessionTranscript, sessionTranscriptSize, ctx->ephemeralPublicKey,
-                  EIC_P256_PUB_KEY_SIZE / 2) == NULL) {
-        eicDebug("Error finding X from ephemeralPublicKey in sessionTranscript");
-        return false;
-    }
-    if (eicMemMem(sessionTranscript, sessionTranscriptSize,
-                  ctx->ephemeralPublicKey + EIC_P256_PUB_KEY_SIZE / 2,
-                  EIC_P256_PUB_KEY_SIZE / 2) == NULL) {
-        eicDebug("Error finding Y from ephemeralPublicKey in sessionTranscript");
-        return false;
+    if (ctx->getEphemeralKeyPairCalled) {
+        if (eicMemMem(sessionTranscript, sessionTranscriptSize, ctx->ephemeralPublicKey,
+                      EIC_P256_PUB_KEY_SIZE / 2) == NULL) {
+            eicDebug("Error finding X from ephemeralPublicKey in sessionTranscript");
+            return false;
+        }
+        if (eicMemMem(sessionTranscript, sessionTranscriptSize,
+                      ctx->ephemeralPublicKey + EIC_P256_PUB_KEY_SIZE / 2,
+                      EIC_P256_PUB_KEY_SIZE / 2) == NULL) {
+            eicDebug("Error finding Y from ephemeralPublicKey in sessionTranscript");
+            return false;
+        }
     }
 
     // To save space we only store the SHA-256 of SessionTranscript
diff --git a/identity/aidl/default/libeic/EicSession.h b/identity/aidl/default/libeic/EicSession.h
index 0303dae..ae9babf 100644
--- a/identity/aidl/default/libeic/EicSession.h
+++ b/identity/aidl/default/libeic/EicSession.h
@@ -31,6 +31,9 @@
     // A non-zero number unique for this EicSession instance
     uint32_t id;
 
+    // Set to true iff eicSessionGetEphemeralKeyPair() has been called.
+    bool getEphemeralKeyPairCalled;
+
     // The challenge generated at construction time by eicSessionInit().
     uint64_t authChallenge;
 
@@ -41,6 +44,7 @@
 
     uint8_t sessionTranscriptSha256[EIC_SHA256_DIGEST_SIZE];
 
+    size_t readerEphemeralPublicKeySize;
 } EicSession;
 
 bool eicSessionInit(EicSession* ctx);
diff --git a/identity/aidl/vts/EndToEndTests.cpp b/identity/aidl/vts/EndToEndTests.cpp
index 67db915..ae9035b 100644
--- a/identity/aidl/vts/EndToEndTests.cpp
+++ b/identity/aidl/vts/EndToEndTests.cpp
@@ -441,8 +441,18 @@
     }
 
     vector<uint8_t> mac;
+    vector<uint8_t> ecdsaSignature;
     vector<uint8_t> deviceNameSpacesEncoded;
-    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+    // API version 5 (feature version 202301) returns both MAC and ECDSA signature.
+    if (halApiVersion_ >= 5) {
+        ASSERT_TRUE(credential
+                            ->finishRetrievalWithSignature(&mac, &deviceNameSpacesEncoded,
+                                                           &ecdsaSignature)
+                            .isOk());
+        ASSERT_GT(ecdsaSignature.size(), 0);
+    } else {
+        ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+    }
     cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
     ASSERT_EQ(
             "{\n"
@@ -475,6 +485,21 @@
     ASSERT_TRUE(calculatedMac);
     EXPECT_EQ(mac, calculatedMac);
 
+    if (ecdsaSignature.size() > 0) {
+        vector<uint8_t> encodedDeviceAuthentication =
+                cppbor::Array()
+                        .add("DeviceAuthentication")
+                        .add(sessionTranscript.clone())
+                        .add(docType)
+                        .add(cppbor::SemanticTag(24, deviceNameSpacesEncoded))
+                        .encode();
+        vector<uint8_t> deviceAuthenticationBytes =
+                cppbor::SemanticTag(24, encodedDeviceAuthentication).encode();
+        EXPECT_TRUE(support::coseCheckEcDsaSignature(ecdsaSignature,
+                                                     deviceAuthenticationBytes,  // Detached content
+                                                     signingPubKey.value()));
+    }
+
     // Also perform an additional empty request. This is what mDL applications
     // are envisioned to do - one call to get the data elements, another to get
     // an empty DeviceSignedItems and corresponding MAC.
@@ -486,7 +511,16 @@
                                 signingKeyBlob, sessionTranscriptEncoded, {},  // readerSignature,
                                 testEntriesEntryCounts)
                         .isOk());
-    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+    // API version 5 (feature version 202301) returns both MAC and ECDSA signature.
+    if (halApiVersion_ >= 5) {
+        ASSERT_TRUE(credential
+                            ->finishRetrievalWithSignature(&mac, &deviceNameSpacesEncoded,
+                                                           &ecdsaSignature)
+                            .isOk());
+        ASSERT_GT(ecdsaSignature.size(), 0);
+    } else {
+        ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+    }
     cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
     ASSERT_EQ("{}", cborPretty);
     // Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
@@ -497,6 +531,21 @@
     ASSERT_TRUE(calculatedMac);
     EXPECT_EQ(mac, calculatedMac);
 
+    if (ecdsaSignature.size() > 0) {
+        vector<uint8_t> encodedDeviceAuthentication =
+                cppbor::Array()
+                        .add("DeviceAuthentication")
+                        .add(sessionTranscript.clone())
+                        .add(docType)
+                        .add(cppbor::SemanticTag(24, deviceNameSpacesEncoded))
+                        .encode();
+        vector<uint8_t> deviceAuthenticationBytes =
+                cppbor::SemanticTag(24, encodedDeviceAuthentication).encode();
+        EXPECT_TRUE(support::coseCheckEcDsaSignature(ecdsaSignature,
+                                                     deviceAuthenticationBytes,  // Detached content
+                                                     signingPubKey.value()));
+    }
+
     // Some mDL apps might send a request but with a single empty
     // namespace. Check that too.
     RequestNamespace emptyRequestNS;
@@ -508,7 +557,16 @@
                                 signingKeyBlob, sessionTranscriptEncoded, {},  // readerSignature,
                                 testEntriesEntryCounts)
                         .isOk());
-    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+    // API version 5 (feature version 202301) returns both MAC and ECDSA signature.
+    if (halApiVersion_ >= 5) {
+        ASSERT_TRUE(credential
+                            ->finishRetrievalWithSignature(&mac, &deviceNameSpacesEncoded,
+                                                           &ecdsaSignature)
+                            .isOk());
+        ASSERT_GT(ecdsaSignature.size(), 0);
+    } else {
+        ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+    }
     cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
     ASSERT_EQ("{}", cborPretty);
     // Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
@@ -518,6 +576,248 @@
                                      eMacKey.value());            // EMacKey
     ASSERT_TRUE(calculatedMac);
     EXPECT_EQ(mac, calculatedMac);
+
+    if (ecdsaSignature.size() > 0) {
+        vector<uint8_t> encodedDeviceAuthentication =
+                cppbor::Array()
+                        .add("DeviceAuthentication")
+                        .add(sessionTranscript.clone())
+                        .add(docType)
+                        .add(cppbor::SemanticTag(24, deviceNameSpacesEncoded))
+                        .encode();
+        vector<uint8_t> deviceAuthenticationBytes =
+                cppbor::SemanticTag(24, encodedDeviceAuthentication).encode();
+        EXPECT_TRUE(support::coseCheckEcDsaSignature(ecdsaSignature,
+                                                     deviceAuthenticationBytes,  // Detached content
+                                                     signingPubKey.value()));
+    }
+}
+
+TEST_P(EndToEndTests, noSessionEncryption) {
+    if (halApiVersion_ < 5) {
+        GTEST_SKIP() << "Need HAL API version 5, have " << halApiVersion_;
+    }
+
+    const vector<test_utils::TestProfile> testProfiles = {// Profile 0 (no authentication)
+                                                          {0, {}, false, 0}};
+
+    HardwareAuthToken authToken;
+    VerificationToken verificationToken;
+    authToken.challenge = 0;
+    authToken.userId = 0;
+    authToken.authenticatorId = 0;
+    authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
+    authToken.timestamp.milliSeconds = 0;
+    authToken.mac.clear();
+    verificationToken.challenge = 0;
+    verificationToken.timestamp.milliSeconds = 0;
+    verificationToken.securityLevel = ::android::hardware::keymaster::SecurityLevel::SOFTWARE;
+    verificationToken.mac.clear();
+
+    // Here's the actual test data:
+    const vector<test_utils::TestEntryData> testEntries = {
+            {"PersonalData", "Last name", string("Turing"), vector<int32_t>{0}},
+            {"PersonalData", "Birth date", string("19120623"), vector<int32_t>{0}},
+            {"PersonalData", "First name", string("Alan"), vector<int32_t>{0}},
+    };
+    const vector<int32_t> testEntriesEntryCounts = {3};
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+    string cborPretty;
+    sp<IWritableIdentityCredential> writableCredential;
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    true /* testCredential */));
+
+    string challenge = "attestationChallenge";
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {1} /* atteestationApplicationId */);
+    ASSERT_TRUE(attData.result.isOk())
+            << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
+
+    // This is kinda of a hack but we need to give the size of
+    // ProofOfProvisioning that we'll expect to receive.
+    const int32_t expectedProofOfProvisioningSize = 230;
+    // OK to fail, not available in v1 HAL
+    writableCredential->setExpectedProofOfProvisioningSize(expectedProofOfProvisioningSize);
+    ASSERT_TRUE(
+            writableCredential->startPersonalization(testProfiles.size(), testEntriesEntryCounts)
+                    .isOk());
+
+    optional<vector<SecureAccessControlProfile>> secureProfiles =
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
+    ASSERT_TRUE(secureProfiles);
+
+    // Uses TestEntryData* pointer as key and values are the encrypted blobs. This
+    // is a little hacky but it works well enough.
+    map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
+
+    for (const auto& entry : testEntries) {
+        ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
+                                         encryptedBlobs, true));
+    }
+
+    vector<uint8_t> credentialData;
+    vector<uint8_t> proofOfProvisioningSignature;
+    ASSERT_TRUE(
+            writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature)
+                    .isOk());
+
+    // Validate the proofOfProvisioning which was returned
+    optional<vector<uint8_t>> proofOfProvisioning =
+            support::coseSignGetPayload(proofOfProvisioningSignature);
+    ASSERT_TRUE(proofOfProvisioning);
+    cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
+    EXPECT_EQ(
+            "[\n"
+            "  'ProofOfProvisioning',\n"
+            "  'org.iso.18013-5.2019.mdl',\n"
+            "  [\n"
+            "    {\n"
+            "      'id' : 0,\n"
+            "    },\n"
+            "  ],\n"
+            "  {\n"
+            "    'PersonalData' : [\n"
+            "      {\n"
+            "        'name' : 'Last name',\n"
+            "        'value' : 'Turing',\n"
+            "        'accessControlProfiles' : [0, ],\n"
+            "      },\n"
+            "      {\n"
+            "        'name' : 'Birth date',\n"
+            "        'value' : '19120623',\n"
+            "        'accessControlProfiles' : [0, ],\n"
+            "      },\n"
+            "      {\n"
+            "        'name' : 'First name',\n"
+            "        'value' : 'Alan',\n"
+            "        'accessControlProfiles' : [0, ],\n"
+            "      },\n"
+            "    ],\n"
+            "  },\n"
+            "  true,\n"
+            "]",
+            cborPretty);
+
+    optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
+            attData.attestationCertificate[0].encodedCertificate);
+    ASSERT_TRUE(credentialPubKey);
+    EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
+                                                 {},  // Additional data
+                                                 credentialPubKey.value()));
+    writableCredential = nullptr;
+
+    // Extract doctype, storage key, and credentialPrivKey from credentialData... this works
+    // only because we asked for a test-credential meaning that the HBK is all zeroes.
+    auto [exSuccess, exDocType, exStorageKey, exCredentialPrivKey, exSha256Pop] =
+            extractFromTestCredentialData(credentialData);
+
+    ASSERT_TRUE(exSuccess);
+    ASSERT_EQ(exDocType, "org.iso.18013-5.2019.mdl");
+    // ... check that the public key derived from the private key matches what was
+    // in the certificate.
+    optional<vector<uint8_t>> exCredentialKeyPair =
+            support::ecPrivateKeyToKeyPair(exCredentialPrivKey);
+    ASSERT_TRUE(exCredentialKeyPair);
+    optional<vector<uint8_t>> exCredentialPubKey =
+            support::ecKeyPairGetPublicKey(exCredentialKeyPair.value());
+    ASSERT_TRUE(exCredentialPubKey);
+    ASSERT_EQ(exCredentialPubKey.value(), credentialPubKey.value());
+
+    sp<IIdentityCredential> credential;
+    ASSERT_TRUE(credentialStore_
+                        ->getCredential(
+                                CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
+                                credentialData, &credential)
+                        .isOk());
+    ASSERT_NE(credential, nullptr);
+
+    // Calculate sessionTranscript, make something that resembles what you'd use for
+    // an over-the-Internet presentation not using mdoc session encryption.
+    cppbor::Array sessionTranscript =
+            cppbor::Array()
+                    .add(cppbor::Null())  // DeviceEngagementBytes isn't used.
+                    .add(cppbor::Null())  // EReaderKeyBytes isn't used.
+                    .add(cppbor::Array()  // Proprietary handover structure follows.
+                                 .add(cppbor::Tstr("TestHandover"))
+                                 .add(cppbor::Bstr(vector<uint8_t>{1, 2, 3}))
+                                 .add(cppbor::Bstr(vector<uint8_t>{9, 8, 7, 6})));
+    vector<uint8_t> sessionTranscriptEncoded = sessionTranscript.encode();
+
+    // Generate the key that will be used to sign AuthenticatedData.
+    vector<uint8_t> signingKeyBlob;
+    Certificate signingKeyCertificate;
+    ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
+    optional<vector<uint8_t>> signingPubKey =
+            support::certificateChainGetTopMostKey(signingKeyCertificate.encodedCertificate);
+    EXPECT_TRUE(signingPubKey);
+    test_utils::verifyAuthKeyCertificate(signingKeyCertificate.encodedCertificate);
+
+    vector<RequestNamespace> requestedNamespaces = test_utils::buildRequestNamespaces(testEntries);
+    ASSERT_TRUE(credential->setRequestedNamespaces(requestedNamespaces).isOk());
+    ASSERT_TRUE(credential->setVerificationToken(verificationToken).isOk());
+    Status status = credential->startRetrieval(
+            secureProfiles.value(), authToken, {} /* itemsRequestBytes*/, signingKeyBlob,
+            sessionTranscriptEncoded, {} /* readerSignature */, testEntriesEntryCounts);
+    ASSERT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
+
+    for (const auto& entry : testEntries) {
+        ASSERT_TRUE(credential
+                            ->startRetrieveEntryValue(entry.nameSpace, entry.name,
+                                                      entry.valueCbor.size(), entry.profileIds)
+                            .isOk());
+
+        auto it = encryptedBlobs.find(&entry);
+        ASSERT_NE(it, encryptedBlobs.end());
+        const vector<vector<uint8_t>>& encryptedChunks = it->second;
+
+        vector<uint8_t> content;
+        for (const auto& encryptedChunk : encryptedChunks) {
+            vector<uint8_t> chunk;
+            ASSERT_TRUE(credential->retrieveEntryValue(encryptedChunk, &chunk).isOk());
+            content.insert(content.end(), chunk.begin(), chunk.end());
+        }
+        EXPECT_EQ(content, entry.valueCbor);
+    }
+
+    vector<uint8_t> mac;
+    vector<uint8_t> ecdsaSignature;
+    vector<uint8_t> deviceNameSpacesEncoded;
+    status = credential->finishRetrievalWithSignature(&mac, &deviceNameSpacesEncoded,
+                                                      &ecdsaSignature);
+    ASSERT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
+    // MACing should NOT work since we're not using session encryption
+    ASSERT_EQ(0, mac.size());
+
+    // ECDSA signatures should work, however. Check this.
+    ASSERT_GT(ecdsaSignature.size(), 0);
+
+    cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
+    ASSERT_EQ(
+            "{\n"
+            "  'PersonalData' : {\n"
+            "    'Last name' : 'Turing',\n"
+            "    'Birth date' : '19120623',\n"
+            "    'First name' : 'Alan',\n"
+            "  },\n"
+            "}",
+            cborPretty);
+
+    string docType = "org.iso.18013-5.2019.mdl";
+
+    vector<uint8_t> encodedDeviceAuthentication =
+            cppbor::Array()
+                    .add("DeviceAuthentication")
+                    .add(sessionTranscript.clone())
+                    .add(docType)
+                    .add(cppbor::SemanticTag(24, deviceNameSpacesEncoded))
+                    .encode();
+    vector<uint8_t> deviceAuthenticationBytes =
+            cppbor::SemanticTag(24, encodedDeviceAuthentication).encode();
+    EXPECT_TRUE(support::coseCheckEcDsaSignature(ecdsaSignature,
+                                                 deviceAuthenticationBytes,  // Detached content
+                                                 signingPubKey.value()));
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EndToEndTests);
diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerType.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerType.aidl
index ce3e1f5..28bd59e 100644
--- a/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerType.aidl
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerType.aidl
@@ -40,4 +40,5 @@
   GNSS = 4,
   MOBILE_RADIO = 5,
   WIFI = 6,
+  CAMERA = 7,
 }
diff --git a/power/stats/aidl/android/hardware/power/stats/EnergyConsumerType.aidl b/power/stats/aidl/android/hardware/power/stats/EnergyConsumerType.aidl
index d871ced..ea70785 100644
--- a/power/stats/aidl/android/hardware/power/stats/EnergyConsumerType.aidl
+++ b/power/stats/aidl/android/hardware/power/stats/EnergyConsumerType.aidl
@@ -26,4 +26,5 @@
     GNSS,
     MOBILE_RADIO,
     WIFI,
+    CAMERA,
 }
diff --git a/radio/aidl/Android.bp b/radio/aidl/Android.bp
index 9dbe09a..930b6d4 100644
--- a/radio/aidl/Android.bp
+++ b/radio/aidl/Android.bp
@@ -12,6 +12,7 @@
     vendor_available: true,
     host_supported: true,
     srcs: ["android/hardware/radio/*.aidl"],
+    frozen: false,
     stability: "vintf",
     backend: {
         cpp: {
@@ -35,6 +36,7 @@
     vendor_available: true,
     host_supported: true,
     srcs: ["android/hardware/radio/config/*.aidl"],
+    frozen: false,
     stability: "vintf",
     imports: ["android.hardware.radio-V2"],
     backend: {
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl
index da894cd..c264dfd 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl
@@ -38,5 +38,5 @@
   String atr;
   String eid;
   android.hardware.radio.config.SimPortInfo[] portInfo;
-  android.hardware.radio.config.MultipleEnabledProfilesMode supportedMepMode;
+  android.hardware.radio.config.MultipleEnabledProfilesMode supportedMepMode = android.hardware.radio.config.MultipleEnabledProfilesMode.NONE;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
index 5aed024..be06c47 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
@@ -78,6 +78,7 @@
   oneway void cancelEmergencyNetworkScan(int serial, boolean resetScan);
   oneway void exitEmergencyMode(in int serial);
   oneway void setNullCipherAndIntegrityEnabled(in int serial, in boolean enabled);
+  oneway void isNullCipherAndIntegrityEnabled(in int serial);
   oneway void isN1ModeEnabled(in int serial);
   oneway void setN1ModeEnabled(in int serial, boolean enable);
   oneway void setLocationPrivacySetting(in int serial, in boolean shareLocation);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
index ccdfde6..009fdd3 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -77,6 +77,7 @@
   oneway void exitEmergencyModeResponse(in android.hardware.radio.RadioResponseInfo info);
   oneway void cancelEmergencyNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
   oneway void setNullCipherAndIntegrityEnabledResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void isNullCipherAndIntegrityEnabledResponse(in android.hardware.radio.RadioResponseInfo info, in boolean isEnabled);
   oneway void isN1ModeEnabledResponse(in android.hardware.radio.RadioResponseInfo info, boolean isEnabled);
   oneway void setN1ModeEnabledResponse(in android.hardware.radio.RadioResponseInfo info);
   oneway void setLocationPrivacySettingResponse(in android.hardware.radio.RadioResponseInfo info);
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 9000d43..46cb7be 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
@@ -44,6 +44,7 @@
   String iccid;
   String eid;
   android.hardware.radio.config.SlotPortMapping slotMap;
+  android.hardware.radio.config.MultipleEnabledProfilesMode supportedMepMode = android.hardware.radio.config.MultipleEnabledProfilesMode.NONE;
   const int STATE_ABSENT = 0;
   const int STATE_PRESENT = 1;
   const int STATE_ERROR = 2;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl
index 2f2e07b..c391e5a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl
@@ -41,5 +41,5 @@
   int p2;
   int p3;
   String data;
-  boolean isEs10;
+  boolean isEs10 = false;
 }
diff --git a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
index 73f2954..6a36d5e 100644
--- a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
+++ b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
@@ -54,7 +54,8 @@
      */
     SimPortInfo[] portInfo;
     /**
-     * Jointly supported Multiple Enabled Profiles(MEP) mode as per SGP.22 V3.0
+     * Jointly supported Multiple Enabled Profiles(MEP) mode as per SGP.22 V3.0. Should always
+     * report proper MEP mode irrespective of whether the slot is active or inactive.
      */
-    MultipleEnabledProfilesMode supportedMepMode;
+    MultipleEnabledProfilesMode supportedMepMode = MultipleEnabledProfilesMode.NONE;
 }
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index 70427f8..38772cd 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -510,6 +510,21 @@
     void setNullCipherAndIntegrityEnabled(in int serial, in boolean enabled);
 
     /**
+     * Get whether null encryption and integrity modes are enabled.
+     *
+     * Null ciphering and integrity modes include, (but are not limited to):
+     * 2G: A5/0, GAE0 (no integrity algorithm supported)
+     * 3G: UEA0 and UIA0
+     * 4G: EEA0 and EIA
+     * 5G: NEA0 and NIA0
+     *
+     * @param serial Serial number of the request.
+     *
+     * Response callback is IRadioNetworkResponse.isNullCipherAndIntegrityEnabledResponse()
+     */
+    void isNullCipherAndIntegrityEnabled(in int serial);
+
+    /**
      * Checks whether N1 mode (access to 5G core network) is enabled or not.
      *
      * @param serial Serial number of request.
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 3fa6521..399dbb7 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -626,6 +626,17 @@
     void setNullCipherAndIntegrityEnabledResponse(in RadioResponseInfo info);
 
     /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param enabled the last known state of null ciphering and integrity algorithms
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:MODEM_ERR
+     */
+    void isNullCipherAndIntegrityEnabledResponse(in RadioResponseInfo info, in boolean isEnabled);
+
+    /**
      * Response of isN1ModeEnabled.
      * This is an optional API.
      *
diff --git a/radio/aidl/android/hardware/radio/sim/CardStatus.aidl b/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
index a14cf7d..1419c51 100644
--- a/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
+++ b/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.radio.sim;
 
+import android.hardware.radio.config.MultipleEnabledProfilesMode;
 import android.hardware.radio.config.SlotPortMapping;
 import android.hardware.radio.sim.AppStatus;
 import android.hardware.radio.sim.PinState;
@@ -93,4 +94,8 @@
      * PortId is the id (enumerated value) for the associated port available on the SIM.
      */
     SlotPortMapping slotMap;
+    /**
+     * Jointly supported Multiple Enabled Profiles(MEP) mode as per SGP.22 V3.0
+     */
+    MultipleEnabledProfilesMode supportedMepMode = MultipleEnabledProfilesMode.NONE;
 }
diff --git a/radio/aidl/android/hardware/radio/sim/SimApdu.aidl b/radio/aidl/android/hardware/radio/sim/SimApdu.aidl
index 4759e2e..9799f2b 100644
--- a/radio/aidl/android/hardware/radio/sim/SimApdu.aidl
+++ b/radio/aidl/android/hardware/radio/sim/SimApdu.aidl
@@ -53,5 +53,5 @@
      * isEs10 indicates that the current streaming APDU contains an ES10 command or it is a regular
      * APDU. (As per spec SGP.22 V3.0, ES10 commands needs to be sent over command port of MEP-A1)
      */
-    boolean isEs10;
+    boolean isEs10 = false;
 }
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
index b446103..45c1645 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
@@ -103,6 +103,7 @@
     ::ndk::ScopedAStatus setN1ModeEnabled(int32_t serial, bool enable) override;
 
     ::ndk::ScopedAStatus setNullCipherAndIntegrityEnabled(int32_t serial, bool enabled) override;
+    ::ndk::ScopedAStatus isNullCipherAndIntegrityEnabled(int32_t serial) override;
 
     ::ndk::ScopedAStatus setLocationPrivacySetting(int32_t serial, bool shareLocation) override;
     ::ndk::ScopedAStatus getLocationPrivacySetting(int32_t serial) override;
diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
index 730b5dd..5e44fff 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -347,6 +347,13 @@
     return ok();
 }
 
+ScopedAStatus RadioNetwork::isNullCipherAndIntegrityEnabled(int32_t serial) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " isNullCipherAndIntegrityEnabled is unsupported by HIDL HALs";
+    respond()->isNullCipherAndIntegrityEnabledResponse(notSupported(serial), true);
+    return ok();
+}
+
 ScopedAStatus RadioNetwork::isN1ModeEnabled(int32_t serial) {
     LOG_CALL << serial;
     LOG(ERROR) << " isN1ModeEnabled is unsupported by HIDL HALs";
diff --git a/radio/aidl/vts/radio_network_response.cpp b/radio/aidl/vts/radio_network_response.cpp
index 4f0e4f3..35e4202 100644
--- a/radio/aidl/vts/radio_network_response.cpp
+++ b/radio/aidl/vts/radio_network_response.cpp
@@ -301,6 +301,13 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus RadioNetworkResponse::isNullCipherAndIntegrityEnabledResponse(
+        const RadioResponseInfo& info, bool /*isEnabled*/) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus RadioNetworkResponse::isN1ModeEnabledResponse(
         const RadioResponseInfo& info, bool /*isEnabled*/) {
     rspInfo = info;
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
index e7a48bc..43a4737 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -1979,3 +1979,23 @@
             {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
     LOG(DEBUG) << "setNullCipherAndIntegrityEnabled finished";
 }
+
+/**
+ * Test IRadioNetwork.isNullCipherAndIntegrityEnabled() for the response returned.
+ */
+TEST_P(RadioNetworkTest, isNullCipherAndIntegrityEnabled) {
+    LOG(DEBUG) << "isNullCipherAndIntegrityEnabled";
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_network->isNullCipherAndIntegrityEnabled(serial);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_network->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
+    LOG(DEBUG) << "isNullCipherAndIntegrityEnabled finished";
+}
diff --git a/radio/aidl/vts/radio_network_utils.h b/radio/aidl/vts/radio_network_utils.h
index 92dcb1f..496ec03 100644
--- a/radio/aidl/vts/radio_network_utils.h
+++ b/radio/aidl/vts/radio_network_utils.h
@@ -162,6 +162,9 @@
     virtual ndk::ScopedAStatus setNullCipherAndIntegrityEnabledResponse(
             const RadioResponseInfo& info) override;
 
+    virtual ndk::ScopedAStatus isNullCipherAndIntegrityEnabledResponse(
+            const RadioResponseInfo& info, const bool isEnabled) override;
+
     virtual ndk::ScopedAStatus isN1ModeEnabledResponse(
             const RadioResponseInfo& info, bool isEnabled) override;
 
diff --git a/security/keymint/aidl/default/android.hardware.hardware_keystore.xml b/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
index 2ebf1fe..4c75596 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="200" />
+  <feature name="android.hardware.hardware_keystore" version="300" />
 </permissions>
diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl
index f60f5bb..b26040b 100644
--- a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl
+++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl
@@ -58,6 +58,8 @@
   const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_DATA = 24;
   const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_RESERVED = 88;
   const int DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH = 104;
+  const int RUNTIME_SENSORS_HANDLE_BASE = 1593835520;
+  const int RUNTIME_SENSORS_HANDLE_END = 1610612735;
   @Backing(type="int") @VintfStability
   enum RateLevel {
     STOP = 0,
diff --git a/sensors/aidl/android/hardware/sensors/ISensors.aidl b/sensors/aidl/android/hardware/sensors/ISensors.aidl
index 2c68489..5e276dd 100644
--- a/sensors/aidl/android/hardware/sensors/ISensors.aidl
+++ b/sensors/aidl/android/hardware/sensors/ISensors.aidl
@@ -371,4 +371,13 @@
     const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_DATA = 0x18;
     const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_RESERVED = 0x58;
     const int DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH = 104;
+
+    /**
+     * Constants related to reserved sensor handle ranges.
+     *
+     * The following range (inclusive) is reserved for usage by the system for
+     * runtime sensors.
+     */
+    const int RUNTIME_SENSORS_HANDLE_BASE = 0x5F000000;
+    const int RUNTIME_SENSORS_HANDLE_END = 0x5FFFFFFF;
 }
diff --git a/sensors/aidl/convert/Android.bp b/sensors/aidl/convert/Android.bp
index 0b31597..53060b9 100644
--- a/sensors/aidl/convert/Android.bp
+++ b/sensors/aidl/convert/Android.bp
@@ -35,7 +35,7 @@
         "libhardware",
         "libbase",
         "libutils",
-        "android.hardware.sensors-V1-ndk",
+        "android.hardware.sensors-V2-ndk",
     ],
     whole_static_libs: [
         "sensors_common_convert",
diff --git a/sensors/aidl/default/Android.bp b/sensors/aidl/default/Android.bp
index 3c66744..16b4d35 100644
--- a/sensors/aidl/default/Android.bp
+++ b/sensors/aidl/default/Android.bp
@@ -41,7 +41,7 @@
         "libfmq",
         "libpower",
         "libbinder_ndk",
-        "android.hardware.sensors-V1-ndk",
+        "android.hardware.sensors-V2-ndk",
     ],
     export_include_dirs: ["include"],
     srcs: [
@@ -68,7 +68,7 @@
         "libcutils",
         "liblog",
         "libutils",
-        "android.hardware.sensors-V1-ndk",
+        "android.hardware.sensors-V2-ndk",
     ],
     static_libs: [
         "libsensorsexampleimpl",
diff --git a/sensors/aidl/default/multihal/Android.bp b/sensors/aidl/default/multihal/Android.bp
index eee1062..a20d6d7 100644
--- a/sensors/aidl/default/multihal/Android.bp
+++ b/sensors/aidl/default/multihal/Android.bp
@@ -38,7 +38,7 @@
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@2.0",
         "android.hardware.sensors@2.1",
-        "android.hardware.sensors-V1-ndk",
+        "android.hardware.sensors-V2-ndk",
     ],
     export_include_dirs: ["include"],
     srcs: [
diff --git a/sensors/aidl/default/sensors-default.xml b/sensors/aidl/default/sensors-default.xml
index 7898a6b..36b28ed 100644
--- a/sensors/aidl/default/sensors-default.xml
+++ b/sensors/aidl/default/sensors-default.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.sensors</name>
-        <version>1</version>
+        <version>2</version>
         <fqname>ISensors/default</fqname>
     </hal>
 </manifest>
diff --git a/sensors/aidl/multihal/Android.bp b/sensors/aidl/multihal/Android.bp
index 6d35daf..522d305 100644
--- a/sensors/aidl/multihal/Android.bp
+++ b/sensors/aidl/multihal/Android.bp
@@ -40,7 +40,7 @@
         "android.hardware.sensors@2.0-ScopedWakelock",
         "android.hardware.sensors@2.0",
         "android.hardware.sensors@2.1",
-        "android.hardware.sensors-V1-ndk",
+        "android.hardware.sensors-V2-ndk",
         "libbase",
         "libcutils",
         "libfmq",
diff --git a/sensors/aidl/multihal/android.hardware.sensors-multihal.xml b/sensors/aidl/multihal/android.hardware.sensors-multihal.xml
index d78edff..5da4fbd 100644
--- a/sensors/aidl/multihal/android.hardware.sensors-multihal.xml
+++ b/sensors/aidl/multihal/android.hardware.sensors-multihal.xml
@@ -17,7 +17,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.sensors</name>
-        <version>1</version>
+        <version>2</version>
         <fqname>ISensors/default</fqname>
     </hal>
 </manifest>
diff --git a/sensors/aidl/vts/Android.bp b/sensors/aidl/vts/Android.bp
index f3972ec..c17a558 100644
--- a/sensors/aidl/vts/Android.bp
+++ b/sensors/aidl/vts/Android.bp
@@ -41,7 +41,7 @@
         "android.hardware.common.fmq-V1-ndk",
     ],
     static_libs: [
-        "android.hardware.sensors-V1-ndk",
+        "android.hardware.sensors-V2-ndk",
         "VtsHalSensorsTargetTestUtils",
         "libaidlcommonsupport",
     ],
diff --git a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
index d536e29..ad58e21 100644
--- a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
+++ b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
@@ -560,10 +560,15 @@
             EXPECT_NO_FATAL_FAILURE(assertTypeMatchStringType(info.type, info.typeAsString));
         }
 
-        // Test if all sensor has name and vendor
+        // Test if all sensors have name and vendor
         EXPECT_FALSE(info.name.empty());
         EXPECT_FALSE(info.vendor.empty());
 
+        // Make sure that the sensor handle is not within the reserved range for runtime
+        // sensors.
+        EXPECT_FALSE(ISensors::RUNTIME_SENSORS_HANDLE_BASE <= info.sensorHandle &&
+                     info.sensorHandle <= ISensors::RUNTIME_SENSORS_HANDLE_END);
+
         // Make sure that sensors of the same type have a unique name.
         std::vector<std::string>& v = sensorTypeNameMap[static_cast<int32_t>(info.type)];
         bool isUniqueName = std::find(v.begin(), v.end(), info.name) == v.end();
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl
index 647891f..f800e8f 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl
@@ -59,6 +59,7 @@
   @PropagateAllowBlocking android.hardware.wifi.IWifiStaIface getStaIface(in String ifname);
   String[] getStaIfaceNames();
   android.hardware.wifi.WifiRadioCombinationMatrix getSupportedRadioCombinationsMatrix();
+  android.hardware.wifi.WifiChipCapabilities getWifiChipCapabilities();
   android.hardware.wifi.WifiUsableChannel[] getUsableChannels(in android.hardware.wifi.WifiBand band, in android.hardware.wifi.WifiIfaceMode ifaceModeMask, in android.hardware.wifi.IWifiChip.UsableChannelFilter filterMask);
   void registerEventCallback(in android.hardware.wifi.IWifiChipEventCallback callback);
   void removeApIface(in String ifname);
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl
index 2f0dfa1..ac5b93b 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl
@@ -61,6 +61,7 @@
   void stopBackgroundScan(in int cmdId);
   void stopRssiMonitoring(in int cmdId);
   void stopSendingKeepAlivePackets(in int cmdId);
+  void setDtimMultiplier(in int multiplier);
   @Backing(type="int") @VintfStability
   enum StaIfaceCapabilityMask {
     APF = 1,
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChipCapabilities.aidl
similarity index 75%
copy from audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
copy to wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChipCapabilities.aidl
index 8ad4848..48dc8e0 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChipCapabilities.aidl
@@ -31,27 +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.audio.effect;
+package android.hardware.wifi;
 @VintfStability
-union Reverb {
-  android.hardware.audio.effect.VendorExtension vendor;
-  int roomLevelMb;
-  int roomHfLevelMb;
-  int decayTimeMs;
-  int decayHfRatioPm;
-  int levelMb;
-  int delayMs;
-  int diffusionPm;
-  int densityPm;
-  boolean bypass;
-  @VintfStability
-  union Id {
-    int vendorExtensionTag;
-    android.hardware.audio.effect.Reverb.Tag commonTag;
-  }
-  @VintfStability
-  parcelable Capability {
-    android.hardware.audio.effect.VendorExtension extension;
-    int maxDecayTimeMs;
-  }
+parcelable WifiChipCapabilities {
+  int maxMloLinkCount;
+  int maxConcurrentTdlsSessionCount;
 }
diff --git a/wifi/aidl/android/hardware/wifi/IWifiChip.aidl b/wifi/aidl/android/hardware/wifi/IWifiChip.aidl
index fe9a6f3..64692af 100644
--- a/wifi/aidl/android/hardware/wifi/IWifiChip.aidl
+++ b/wifi/aidl/android/hardware/wifi/IWifiChip.aidl
@@ -25,6 +25,7 @@
 import android.hardware.wifi.IfaceConcurrencyType;
 import android.hardware.wifi.IfaceType;
 import android.hardware.wifi.WifiBand;
+import android.hardware.wifi.WifiChipCapabilities;
 import android.hardware.wifi.WifiDebugHostWakeReasonStats;
 import android.hardware.wifi.WifiDebugRingBufferStatus;
 import android.hardware.wifi.WifiDebugRingBufferVerboseLevel;
@@ -785,6 +786,18 @@
     WifiRadioCombinationMatrix getSupportedRadioCombinationsMatrix();
 
     /**
+     * Get capabilities supported by this chip.
+     *
+     * @return Chip capabilities represented by |WifiChipCapabilities|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.FAILURE_UNKNOWN|
+     *
+     */
+    WifiChipCapabilities getWifiChipCapabilities();
+
+    /**
      * Retrieve a list of usable Wifi channels for the specified band &
      * operational modes.
      *
diff --git a/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl b/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl
index 2dd57b2..e6218e6 100644
--- a/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl
+++ b/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl
@@ -552,4 +552,20 @@
      *         |WifiStatusCode.ERROR_UNKNOWN|
      */
     void stopSendingKeepAlivePackets(in int cmdId);
+
+    /**
+     * Set DTIM multiplier used when the system is in the suspended mode.
+     * When STA is in the power saving mode and system is suspended,
+     * the wake up interval will be set to:
+     *              1) multiplier * DTIM period if multiplier > 0.
+     *              2) the driver default value if multiplier <= 0.
+     * Some implementations may apply an additional cap to wake up interval in the case of 1).
+     *
+     * @param multiplier integer DTIM multiplier value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void setDtimMultiplier(in int multiplier);
 }
diff --git a/wifi/aidl/android/hardware/wifi/WifiChipCapabilities.aidl b/wifi/aidl/android/hardware/wifi/WifiChipCapabilities.aidl
new file mode 100644
index 0000000..f65d49a
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiChipCapabilities.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+/**
+ * WifiChipCapabilities captures various Wifi chip capability params.
+ */
+@VintfStability
+parcelable WifiChipCapabilities {
+    /**
+     * Maximum number of links used in Multi-Link Operation. The maximum
+     * number of links used for MLO can be different from the number of
+     * radios supported by the chip.
+     *
+     * This is a static configuration of the chip.
+     */
+    int maxMloLinkCount;
+    /**
+     * Maximum number of concurrent TDLS sessions that can be enabled
+     * by framework via ISupplicantStaIface#initiateTdlsSetup().
+     */
+    int maxConcurrentTdlsSessionCount;
+}
diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp
index 07612b6..ec8b396 100644
--- a/wifi/aidl/default/aidl_struct_util.cpp
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -2768,6 +2768,15 @@
     return true;
 }
 
+bool convertLegacyWifiChipCapabilitiesToAidl(
+        const legacy_hal::wifi_chip_capabilities& legacy_chip_capabilities,
+        WifiChipCapabilities& aidl_chip_capabilities) {
+    aidl_chip_capabilities.maxMloLinkCount = legacy_chip_capabilities.max_mlo_link_count;
+    aidl_chip_capabilities.maxConcurrentTdlsSessionCount =
+            legacy_chip_capabilities.max_concurrent_tdls_session_count;
+    return true;
+}
+
 }  // namespace aidl_struct_util
 }  // namespace wifi
 }  // namespace hardware
diff --git a/wifi/aidl/default/aidl_struct_util.h b/wifi/aidl/default/aidl_struct_util.h
index 4ebfc10..d8e1fd4 100644
--- a/wifi/aidl/default/aidl_struct_util.h
+++ b/wifi/aidl/default/aidl_struct_util.h
@@ -171,6 +171,9 @@
                                       StaPeerInfo* aidl_peer_info_stats);
 bool convertLegacyWifiRateInfoToAidl(const legacy_hal::wifi_rate& legacy_rate,
                                      WifiRateInfo* aidl_rate);
+bool convertLegacyWifiChipCapabilitiesToAidl(
+        const legacy_hal::wifi_chip_capabilities& legacy_chip_capabilities,
+        WifiChipCapabilities& aidl_chip_capabilities);
 }  // namespace aidl_struct_util
 }  // namespace wifi
 }  // namespace hardware
diff --git a/wifi/aidl/default/wifi_chip.cpp b/wifi/aidl/default/wifi_chip.cpp
index 076f351..4061699 100644
--- a/wifi/aidl/default/wifi_chip.cpp
+++ b/wifi/aidl/default/wifi_chip.cpp
@@ -680,6 +680,11 @@
                            &WifiChip::getSupportedRadioCombinationsMatrixInternal, _aidl_return);
 }
 
+ndk::ScopedAStatus WifiChip::getWifiChipCapabilities(WifiChipCapabilities* _aidl_return) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getWifiChipCapabilitiesInternal, _aidl_return);
+}
+
 void WifiChip::invalidateAndRemoveAllIfaces() {
     invalidateAndClearBridgedApAll();
     invalidateAndClearAll(ap_ifaces_);
@@ -1403,6 +1408,26 @@
     return {aidl_matrix, ndk::ScopedAStatus::ok()};
 }
 
+std::pair<WifiChipCapabilities, ndk::ScopedAStatus> WifiChip::getWifiChipCapabilitiesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::wifi_chip_capabilities legacy_chip_capabilities;
+    std::tie(legacy_status, legacy_chip_capabilities) =
+            legacy_hal_.lock()->getWifiChipCapabilities();
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to get chip capabilities from legacy HAL: "
+                   << legacyErrorToString(legacy_status);
+        return {WifiChipCapabilities(), createWifiStatusFromLegacyError(legacy_status)};
+    }
+    WifiChipCapabilities aidl_chip_capabilities;
+    if (!aidl_struct_util::convertLegacyWifiChipCapabilitiesToAidl(legacy_chip_capabilities,
+                                                                   aidl_chip_capabilities)) {
+        LOG(ERROR) << "Failed convertLegacyWifiChipCapabilitiesToAidl() ";
+        return {WifiChipCapabilities(), createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
+    }
+
+    return {aidl_chip_capabilities, ndk::ScopedAStatus::ok()};
+}
+
 ndk::ScopedAStatus WifiChip::triggerSubsystemRestartInternal() {
     auto legacy_status = legacy_hal_.lock()->triggerSubsystemRestart();
     return createWifiStatusFromLegacyError(legacy_status);
diff --git a/wifi/aidl/default/wifi_chip.h b/wifi/aidl/default/wifi_chip.h
index 59eaa4a..7b04e85 100644
--- a/wifi/aidl/default/wifi_chip.h
+++ b/wifi/aidl/default/wifi_chip.h
@@ -144,6 +144,7 @@
     ndk::ScopedAStatus triggerSubsystemRestart() override;
     ndk::ScopedAStatus getSupportedRadioCombinationsMatrix(
             WifiRadioCombinationMatrix* _aidl_return) override;
+    ndk::ScopedAStatus getWifiChipCapabilities(WifiChipCapabilities* _aidl_return) override;
     binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
 
   private:
@@ -250,6 +251,7 @@
     ndk::ScopedAStatus triggerSubsystemRestartInternal();
     std::pair<WifiRadioCombinationMatrix, ndk::ScopedAStatus>
     getSupportedRadioCombinationsMatrixInternal();
+    std::pair<WifiChipCapabilities, ndk::ScopedAStatus> getWifiChipCapabilitiesInternal();
     void setWeakPtr(std::weak_ptr<WifiChip> ptr);
 
     int32_t chip_id_;
diff --git a/wifi/aidl/default/wifi_legacy_hal.cpp b/wifi/aidl/default/wifi_legacy_hal.cpp
index 43e73ca..e4883d1 100644
--- a/wifi/aidl/default/wifi_legacy_hal.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal.cpp
@@ -1609,6 +1609,13 @@
     return status;
 }
 
+std::pair<wifi_error, wifi_chip_capabilities> WifiLegacyHal::getWifiChipCapabilities() {
+    wifi_chip_capabilities chip_capabilities;
+    wifi_error status =
+            global_func_table_.wifi_get_chip_capabilities(global_handle_, &chip_capabilities);
+    return {status, chip_capabilities};
+}
+
 void WifiLegacyHal::invalidate() {
     global_handle_ = nullptr;
     iface_name_to_handle_.clear();
diff --git a/wifi/aidl/default/wifi_legacy_hal.h b/wifi/aidl/default/wifi_legacy_hal.h
index cd8c0b1..33ed359 100644
--- a/wifi/aidl/default/wifi_legacy_hal.h
+++ b/wifi/aidl/default/wifi_legacy_hal.h
@@ -232,6 +232,7 @@
 using ::wifi_channel_info;
 using ::wifi_channel_stat;
 using ::wifi_channel_width;
+using ::wifi_chip_capabilities;
 using ::wifi_coex_restriction;
 using ::wifi_coex_unsafe_channel;
 using ::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED;
@@ -693,6 +694,7 @@
     wifi_error enableWifiTxPowerLimits(const std::string& iface_name, bool enable);
     wifi_error getWifiCachedScanResults(const std::string& iface_name,
                                         const CachedScanResultsCallbackHandlers& handler);
+    std::pair<wifi_error, wifi_chip_capabilities> getWifiChipCapabilities();
 
   private:
     // Retrieve interface handles for all the available interfaces.
diff --git a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
index cff7f69..7777894 100644
--- a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
@@ -167,6 +167,7 @@
     populateStubFor(&hal_fn->wifi_chre_register_handler);
     populateStubFor(&hal_fn->wifi_enable_tx_power_limits);
     populateStubFor(&hal_fn->wifi_get_cached_scan_results);
+    populateStubFor(&hal_fn->wifi_get_chip_capabilities);
     return true;
 }
 
diff --git a/wifi/aidl/default/wifi_sta_iface.cpp b/wifi/aidl/default/wifi_sta_iface.cpp
index ce90349..57384bf 100644
--- a/wifi/aidl/default/wifi_sta_iface.cpp
+++ b/wifi/aidl/default/wifi_sta_iface.cpp
@@ -222,6 +222,11 @@
                            &WifiStaIface::setScanModeInternal, in_enable);
 }
 
+ndk::ScopedAStatus WifiStaIface::setDtimMultiplier(int32_t in_multiplier) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::setDtimMultiplierInternal, in_multiplier);
+}
+
 std::pair<std::string, ndk::ScopedAStatus> WifiStaIface::getNameInternal() {
     return {ifname_, ndk::ScopedAStatus::ok()};
 }
@@ -552,6 +557,11 @@
     return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
 }
 
+ndk::ScopedAStatus WifiStaIface::setDtimMultiplierInternal(const int multiplier) {
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setDtimConfig(ifname_, multiplier);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/aidl/default/wifi_sta_iface.h b/wifi/aidl/default/wifi_sta_iface.h
index 8ac3470..2e4403a 100644
--- a/wifi/aidl/default/wifi_sta_iface.h
+++ b/wifi/aidl/default/wifi_sta_iface.h
@@ -92,6 +92,7 @@
     ndk::ScopedAStatus setMacAddress(const std::array<uint8_t, 6>& in_mac) override;
     ndk::ScopedAStatus getFactoryMacAddress(std::array<uint8_t, 6>* _aidl_return) override;
     ndk::ScopedAStatus setScanMode(bool in_enable) override;
+    ndk::ScopedAStatus setDtimMultiplier(int32_t in_multiplier) override;
 
   private:
     // Corresponding worker functions for the AIDL methods.
@@ -133,6 +134,7 @@
     ndk::ScopedAStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
     std::pair<std::array<uint8_t, 6>, ndk::ScopedAStatus> getFactoryMacAddressInternal();
     ndk::ScopedAStatus setScanModeInternal(bool enable);
+    ndk::ScopedAStatus setDtimMultiplierInternal(const int multiplier);
 
     void setWeakPtr(std::weak_ptr<WifiStaIface> ptr);
 
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
index 6276a35..f9a078b 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
@@ -39,4 +39,5 @@
   oneway void onNetworkEapSimUmtsAuthRequest(in android.hardware.wifi.supplicant.NetworkRequestEapSimUmtsAuthParams params);
   oneway void onTransitionDisable(in android.hardware.wifi.supplicant.TransitionDisableIndication ind);
   oneway void onServerCertificateAvailable(in int depth, in byte[] subject, in byte[] certHash, in byte[] certBlob);
+  oneway void onPermanentIdReqDenied();
 }
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
index de7b675..4f892be 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
@@ -71,4 +71,11 @@
      */
     void onServerCertificateAvailable(
             in int depth, in byte[] subject, in byte[] certHash, in byte[] certBlob);
+
+    /**
+     * Used to notify the AT_PERMANENT_ID_REQ denied event.
+     *
+     * In strict conservative mode, AT_PERMANENT_ID_REQ is denied from eap_peer side.
+     */
+    void onPermanentIdReqDenied();
 }
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
index 6ff64a5..0aebe6d 100644
--- a/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
@@ -100,6 +100,7 @@
             const std::vector<uint8_t>& /* certBlob */) override {
         return ndk::ScopedAStatus::ok();
     }
+    ::ndk::ScopedAStatus onPermanentIdReqDenied() override { return ndk::ScopedAStatus::ok(); }
 };
 
 class SupplicantStaNetworkAidlTest